├── .ansible-lint ├── .flake8 ├── .github ├── labels.yml ├── release-drafter.yml └── workflows │ ├── release-drafter.yml │ └── tox.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .tool-versions ├── .yamllint ├── LICENSE ├── MANIFEST.in ├── README.rst ├── conftest.py ├── molecule_goss ├── __init__.py ├── cookiecutter │ ├── cookiecutter.json │ └── {{cookiecutter.molecule_directory}} │ │ └── {{cookiecutter.scenario_name}} │ │ ├── verify.yml │ │ └── {{cookiecutter.verifier_directory}} │ │ └── test_default.yml ├── goss.py └── test │ ├── conftest.py │ ├── scenarios │ └── docker │ │ ├── centos7 │ │ └── molecule │ │ │ └── default │ │ │ ├── converge.yml │ │ │ ├── molecule.yml │ │ │ ├── tests │ │ │ ├── test_default.yml │ │ │ └── test_install.yml │ │ │ └── verify.yml │ │ └── ubuntu18.04 │ │ └── molecule │ │ └── default │ │ ├── converge.yml │ │ ├── molecule.yml │ │ ├── tests │ │ ├── test_default.yml │ │ └── test_install.yml │ │ └── verify.yml │ └── test_command.py ├── mypy.ini ├── pyproject.toml ├── setup.cfg ├── setup.py ├── tools └── test-setup.sh └── tox.ini /.ansible-lint: -------------------------------------------------------------------------------- 1 | exclude_paths: 2 | - .github 3 | - molecule_inspec/cookiecutter 4 | warn_list: # or 'skip_list' to silence them completely 5 | - '204' # Lines should be no longer than 160 chars 6 | - '301' # Commands should not change things if nothing needs doing 7 | - '403' # Package installs should not use latest 8 | - experimental # all rules tagged as experimental 9 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | # do not add excludes for files in repo 3 | exclude = .venv/,.tox/,dist/,build/,.eggs/ 4 | format = pylint 5 | # E203: https://github.com/python/black/issues/315 6 | ignore = E741,W503,W504,H,E501,E203 7 | # 88 is official black default: 8 | max-line-length = 88 9 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # Format and labels used aim to match those used by Ansible project 2 | # https://github.com/marketplace/actions/github-labeler 3 | - name: bug 4 | color: "fbca04" 5 | description: "This issue/PR relates to a bug." 6 | - name: deprecated 7 | color: "fef2c0" 8 | description: "This issue/PR relates to a deprecated module." 9 | - name: docs 10 | color: "4071a5" 11 | description: "This issue/PR relates to or includes documentation." 12 | - name: enhancement 13 | color: "ededed" 14 | description: "This issue/PR relates to a feature request." 15 | - name: feature 16 | color: "006b75" 17 | description: "This issue/PR relates to a feature request." 18 | - name: major 19 | color: "c6476b" 20 | description: "Marks an important and likely breaking change." 21 | - name: packaging 22 | color: "4071a5" 23 | description: "Packaging category" 24 | - name: performance 25 | color: "555555" 26 | description: "Relates to product or testing performance." 27 | - name: skip-changelog 28 | color: "eeeeee" 29 | description: "Can be missed from the changelog." 30 | - name: stale 31 | color: "eeeeee" 32 | description: "Not updated in long time, will be closed soon." 33 | - name: wontfix 34 | color: "eeeeee" 35 | description: "This will not be worked on" 36 | - name: test 37 | color: "0e8a16" 38 | description: "This PR relates to tests, QA, CI." 39 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Format and labels used aim to match those used by Ansible project 2 | categories: 3 | - title: 'Major Changes' 4 | labels: 5 | - 'major' # c6476b 6 | - title: 'Minor Changes' 7 | labels: 8 | - 'feature' # 006b75 9 | - 'enhancement' # ededed 10 | - 'performance' # 555555 11 | - title: 'Bugfixes' 12 | labels: 13 | - 'fix' 14 | - 'bugfix' 15 | - 'bug' # fbca04 16 | - 'docs' # 4071a5 17 | - 'packaging' # 4071a5 18 | - 'test' # #0e8a16 19 | - title: 'Deprecations' 20 | labels: 21 | - 'deprecated' # fef2c0 22 | exclude-labels: 23 | - 'skip-changelog' 24 | template: | 25 | ## Changes 26 | 27 | $CHANGES 28 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | # branches to consider in the event; optional, defaults to all 6 | branches: 7 | - master 8 | - 'releases/**' 9 | - 'stable/**' 10 | 11 | jobs: 12 | update_release_draft: 13 | runs-on: ubuntu-latest 14 | steps: 15 | # Drafts your next Release notes as Pull Requests are merged into "master" 16 | - uses: release-drafter/release-drafter@v5 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/tox.yml: -------------------------------------------------------------------------------- 1 | name: tox 2 | 3 | on: 4 | create: # is used for publishing to PyPI and TestPyPI 5 | tags: # any tag regardless of its name, no branches 6 | - "**" 7 | push: # only publishes pushes to the main branch to TestPyPI 8 | branches: # any integration branch but not tag 9 | - "master" 10 | tags-ignore: 11 | - "**" 12 | pull_request: 13 | schedule: 14 | - cron: 1 0 * * * # Run daily at 0:01 UTC 15 | 16 | jobs: 17 | build: 18 | name: ${{ matrix.tox_env }} 19 | runs-on: ubuntu-latest 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | include: 24 | - tox_env: lint 25 | # - tox_env: docs 26 | - tox_env: py36 27 | PREFIX: PYTEST_REQPASS=3 28 | - tox_env: py37 29 | PREFIX: PYTEST_REQPASS=3 30 | - tox_env: py38 31 | PREFIX: PYTEST_REQPASS=3 32 | - tox_env: py39 33 | PREFIX: PYTEST_REQPASS=3 34 | - tox_env: packaging 35 | 36 | steps: 37 | - uses: actions/checkout@v1 38 | - name: Find python version 39 | id: py_ver 40 | shell: python 41 | if: ${{ contains(matrix.tox_env, 'py') }} 42 | run: | 43 | v = '${{ matrix.tox_env }}'.split('-')[0].lstrip('py') 44 | print('::set-output name=version::{0}.{1}'.format(v[0],v[1:])) 45 | # Even our lint and other envs need access to tox 46 | - name: Install a default Python 47 | uses: actions/setup-python@v2 48 | if: ${{ ! contains(matrix.tox_env, 'py') }} 49 | # Be sure to install the version of python needed by a specific test, if necessary 50 | - name: Set up Python version 51 | uses: actions/setup-python@v2 52 | if: ${{ contains(matrix.tox_env, 'py') }} 53 | with: 54 | python-version: ${{ steps.py_ver.outputs.version }} 55 | - name: Install dependencies 56 | run: | 57 | docker version 58 | docker info 59 | python -m pip install -U pip 60 | pip install tox 61 | - name: Run tox -e ${{ matrix.tox_env }} 62 | run: | 63 | echo "${{ matrix.PREFIX }} tox -e ${{ matrix.tox_env }}" 64 | ${{ matrix.PREFIX }} tox -e ${{ matrix.tox_env }} 65 | publish: 66 | name: Publish to PyPI registry 67 | needs: 68 | - build 69 | runs-on: ubuntu-latest 70 | 71 | env: 72 | PY_COLORS: 1 73 | TOXENV: packaging 74 | 75 | steps: 76 | - name: Switch to using Python 3.6 by default 77 | uses: actions/setup-python@v2 78 | with: 79 | python-version: 3.6 80 | - name: Install tox 81 | run: python -m pip install --user tox 82 | - name: Check out src from Git 83 | uses: actions/checkout@v2 84 | with: 85 | # Get shallow Git history (default) for tag creation events 86 | # but have a complete clone for any other workflows. 87 | # Both options fetch tags but since we're going to remove 88 | # one from HEAD in non-create-tag workflows, we need full 89 | # history for them. 90 | fetch-depth: >- 91 | ${{ 92 | ( 93 | github.event_name == 'create' && 94 | github.event.ref_type == 'tag' 95 | ) && 96 | 1 || 0 97 | }} 98 | - name: Drop Git tags from HEAD for non-tag-create events 99 | if: >- 100 | github.event_name != 'create' || 101 | github.event.ref_type != 'tag' 102 | run: >- 103 | git tag --points-at HEAD 104 | | 105 | xargs git tag --delete 106 | - name: Build dists 107 | run: python -m tox 108 | - name: Publish to test.pypi.org 109 | if: >- 110 | ( 111 | github.event_name == 'push' && 112 | github.ref == format( 113 | 'refs/heads/{0}', github.event.repository.default_branch 114 | ) 115 | ) || 116 | ( 117 | github.event_name == 'create' && 118 | github.event.ref_type == 'tag' 119 | ) 120 | uses: pypa/gh-action-pypi-publish@master 121 | with: 122 | password: ${{ secrets.testpypi_password }} 123 | repository_url: https://test.pypi.org/legacy/ 124 | - name: Publish to pypi.org 125 | if: >- # "create" workflows run separately from "push" & "pull_request" 126 | github.event_name == 'create' && 127 | github.event.ref_type == 'tag' 128 | uses: pypa/gh-action-pypi-publish@master 129 | with: 130 | password: ${{ secrets.pypi_password }} 131 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | pip-wheel-metadata 106 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | default_language_version: 3 | python: python3 4 | minimum_pre_commit_version: "1.14.0" 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v3.4.0 8 | hooks: 9 | - id: end-of-file-fixer 10 | - id: trailing-whitespace 11 | - id: mixed-line-ending 12 | - id: check-byte-order-marker 13 | - id: check-executables-have-shebangs 14 | - id: check-merge-conflict 15 | - id: debug-statements 16 | - id: check-yaml 17 | files: .*\.(yaml|yml)$ 18 | exclude: 'cookiecutter.*' 19 | # https://github.com/pre-commit/pre-commit-hooks/issues/273 20 | args: ["--unsafe"] 21 | - repo: https://github.com/psf/black.git 22 | rev: 20.8b1 23 | hooks: 24 | - id: black 25 | language_version: python3 26 | - repo: https://gitlab.com/pycqa/flake8.git 27 | rev: 3.8.4 28 | hooks: 29 | - id: flake8 30 | additional_dependencies: 31 | - flake8-black 32 | - repo: https://github.com/codespell-project/codespell.git 33 | rev: v1.16.0 34 | hooks: 35 | - id: codespell 36 | name: codespell 37 | description: Checks for common misspellings in text files. 38 | entry: codespell 39 | language: python 40 | types: [text] 41 | args: [] 42 | require_serial: false 43 | additional_dependencies: [] 44 | - repo: https://github.com/adrienverge/yamllint.git 45 | rev: v1.20.0 46 | hooks: 47 | - id: yamllint 48 | files: \.(yaml|yml)$ 49 | types: [file, yaml] 50 | entry: yamllint --strict -f parsable 51 | - repo: https://github.com/ansible/ansible-lint.git 52 | rev: v4.3.7 53 | hooks: 54 | - id: ansible-lint 55 | files: \.(yaml|yml)$ 56 | exclude: '.github' 57 | always_run: true 58 | pass_filenames: false 59 | # do not add file filters here as ansible-lint does not give reliable 60 | # results when called with individual files. 61 | # https://github.com/ansible/ansible-lint/issues/611 62 | entry: ansible-lint --force-color -p -v 63 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | python 3.8.6 3.6.12 3.7.9 3.9.0 2 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | extends: default 2 | ignore: | 3 | */cookiecutter/ 4 | .github/workflows/ 5 | .tox 6 | 7 | rules: 8 | braces: 9 | max-spaces-inside: 1 10 | level: error 11 | brackets: 12 | max-spaces-inside: 1 13 | level: error 14 | document-start: disable 15 | line-length: disable 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 PyContribs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.rst 3 | 4 | recursive-exclude * __pycache__ 5 | recursive-exclude * *.py[co] 6 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ******************** 2 | Molecule Goss Plugin 3 | ******************** 4 | 5 | .. image:: https://badge.fury.io/py/molecule-goss.svg 6 | :target: https://badge.fury.io/py/molecule-goss 7 | :alt: PyPI Package 8 | 9 | .. image:: https://github.com/ansible-community/molecule-goss/workflows/tox/badge.svg 10 | :target: https://github.com/ansible-community/molecule-goss/actions 11 | 12 | .. image:: https://img.shields.io/badge/code%20style-black-000000.svg 13 | :target: https://github.com/python/black 14 | :alt: Python Black Code Style 15 | 16 | .. image:: https://img.shields.io/badge/Code%20of%20Conduct-silver.svg 17 | :target: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html 18 | :alt: Ansible Code of Conduct 19 | 20 | .. image:: https://img.shields.io/badge/license-MIT-brightgreen.svg 21 | :target: LICENSE 22 | :alt: Repository License 23 | 24 | Molecule goss is designed to allow use of goss Cloud for provisioning test 25 | resources. 26 | 27 | Documentation 28 | ============= 29 | 30 | Read the documentation and more at https://molecule.readthedocs.io/. 31 | 32 | .. _get-involved: 33 | 34 | Get Involved 35 | ============ 36 | 37 | * Join us in the ``#ansible-molecule`` channel on `Freenode`_. 38 | * Join the discussion in `molecule-users Forum`_. 39 | * Join the community working group by checking the `wiki`_. 40 | * Want to know about releases, subscribe to `ansible-announce list`_. 41 | * For the full list of Ansible email Lists, IRC channels see the 42 | `communication page`_. 43 | 44 | .. _`Freenode`: https://freenode.net 45 | .. _`molecule-users Forum`: https://groups.google.com/forum/#!forum/molecule-users 46 | .. _`wiki`: https://github.com/ansible/community/wiki/Molecule 47 | .. _`ansible-announce list`: https://groups.google.com/group/ansible-announce 48 | .. _`communication page`: https://docs.ansible.com/ansible/latest/community/communication.html 49 | 50 | .. _authors: 51 | 52 | Authors 53 | ======= 54 | 55 | Molecule Goss Plugin was created by Sorin Sbarnea based on code from Molecule. 56 | 57 | .. _license: 58 | 59 | License 60 | ======= 61 | 62 | The `MIT`_ License. 63 | 64 | .. _`MIT`: https://github.com/ansible/molecule/blob/master/LICENSE 65 | 66 | The logo is licensed under the `Creative Commons NoDerivatives 4.0 License`_. 67 | 68 | If you have some other use in mind, contact us. 69 | 70 | .. _`Creative Commons NoDerivatives 4.0 License`: https://creativecommons.org/licenses/by-nd/4.0/ 71 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | """Pytest Config.""" 2 | 3 | 4 | pytest_plugins = ["helpers_namespace"] 5 | -------------------------------------------------------------------------------- /molecule_goss/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible-community/molecule-goss/60923317c78fd1658c9508e05a6ab7ba1740bd09/molecule_goss/__init__.py -------------------------------------------------------------------------------- /molecule_goss/cookiecutter/cookiecutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "molecule_directory": "molecule", 3 | 4 | "role_name": "OVERRIDDEN", 5 | "scenario_name": "default", 6 | "verifier_directory": "tests" 7 | } 8 | -------------------------------------------------------------------------------- /molecule_goss/cookiecutter/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | {% raw -%} 3 | - name: Verify 4 | hosts: all 5 | become: true 6 | vars: 7 | goss_version: v0.3.16 8 | goss_arch: amd64 9 | goss_bin: /usr/local/bin/goss 10 | goss_sha256sum: 827e354b48f93bce933f5efcd1f00dc82569c42a179cf2d384b040d8a80bfbfb. 11 | goss_test_directory: /tmp/molecule/goss 12 | goss_format: documentation 13 | goss_vars: "{{ goss_test_directory }}/vars" 14 | copy_defaults_vars: false 15 | tasks: 16 | - name: Download and install Goss 17 | get_url: 18 | url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" 19 | dest: "{{ goss_bin }}" 20 | checksum: "sha256:{{ goss_sha256sum }}" 21 | mode: 0755 22 | 23 | - name: Create Molecule directory for test files 24 | file: 25 | path: "{{ goss_test_directory }}" 26 | state: directory 27 | mode: 0644 28 | 29 | - name: Find Goss tests on localhost 30 | find: 31 | paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" 32 | patterns: 33 | - "test[-.\\w]*.yml" 34 | - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" 35 | excludes: 36 | - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" 37 | use_regex: true 38 | delegate_to: localhost 39 | register: test_files 40 | changed_when: false 41 | become: false 42 | 43 | - name: debug 44 | debug: 45 | msg: "{{ test_files.files }}" 46 | verbosity: 3 47 | 48 | - name: Copy defaults vars to goss vars 49 | copy: 50 | src: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml" 51 | dest: "{{ goss_vars }}" 52 | mode: 0644 53 | when: copy_defaults_vars 54 | 55 | - name: Copy Goss tests to remote 56 | copy: 57 | src: "{{ item.path }}" 58 | dest: "{{ goss_test_directory }}/{{ item.path | basename }}" 59 | mode: 0644 60 | with_items: 61 | - "{{ test_files.files }}" 62 | 63 | - name: Register test files 64 | shell: "ls {{ goss_test_directory }}/test_*.yml" 65 | changed_when: false 66 | register: test_files 67 | 68 | - name: Execute Goss tests 69 | command: 70 | "{{ goss_bin }} 71 | {% if copy_defaults_vars %} 72 | --vars {{ goss_vars }} 73 | {% endif %} 74 | -g {{ item }} validate --format {{ goss_format }}" 75 | register: test_results 76 | with_items: "{{ test_files.stdout_lines }}" 77 | changed_when: false 78 | failed_when: false 79 | 80 | - name: Display details about the Goss results 81 | debug: 82 | msg: "{{ item.stdout_lines }}" 83 | with_items: "{{ test_results.results }}" 84 | 85 | - name: Fail when tests fail 86 | fail: 87 | msg: "Goss failed to validate" 88 | when: item.rc != 0 89 | with_items: "{{ test_results.results }}" 90 | {% endraw -%} 91 | -------------------------------------------------------------------------------- /molecule_goss/cookiecutter/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/{{cookiecutter.verifier_directory}}/test_default.yml: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | --- 4 | file: 5 | /etc/hosts: 6 | exists: true 7 | owner: root 8 | group: root 9 | -------------------------------------------------------------------------------- /molecule_goss/goss.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-2018 Cisco Systems, Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to 5 | # deal in the Software without restriction, including without limitation the 6 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | # sell copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | import os 22 | 23 | from molecule import logger 24 | from molecule import util 25 | from molecule.api import Verifier 26 | 27 | LOG = logger.get_logger(__name__) 28 | 29 | 30 | class Goss(Verifier): 31 | """ 32 | `Goss`_ is not the default test runner. 33 | 34 | `Goss`_ is a YAML based serverspec-like tool for validating a server's 35 | configuration. `Goss`_ is `not` the default verifier used in Molecule. 36 | 37 | Molecule executes a playbook (`verify.yml`) located in the role's 38 | `scenario.directory`. This playbook will copy YAML files to the instances, 39 | and execute Goss using a community written Goss Ansible module bundled with 40 | Molecule. 41 | 42 | Additional options can be passed to ``goss validate`` by modifying the 43 | verify playbook. 44 | 45 | .. code-block:: yaml 46 | 47 | verifier: 48 | name: goss 49 | 50 | The testing can be disabled by setting ``enabled`` to False. 51 | 52 | .. code-block:: yaml 53 | 54 | verifier: 55 | name: goss 56 | enabled: False 57 | 58 | Environment variables can be passed to the verifier. 59 | 60 | .. code-block:: yaml 61 | 62 | verifier: 63 | name: goss 64 | env: 65 | FOO: bar 66 | 67 | Change path to the test directory. 68 | 69 | .. code-block:: yaml 70 | 71 | verifier: 72 | name: goss 73 | directory: /foo/bar/ 74 | 75 | All files starting with test_* will be copied to all molecule hosts. 76 | Files matching the regular expression `test_host_$instance_name[-.\\w].yml` 77 | will only run on $instance_name. If you have 2 molecule instances, 78 | instance1 and instance2, your test files could look like this: 79 | 80 | .. code-block:: bash 81 | 82 | test_default.yml (will run on all hosts) 83 | test_host_instance1.yml (will run only on instance1) 84 | test_host_instance2.yml (will run only on instance2) 85 | 86 | .. important:: 87 | 88 | Due to the nature of this verifier. Molecule does not perform options 89 | handling in the same fashion as Testinfra. 90 | 91 | .. _`Goss`: https://github.com/aelsabbahy/goss 92 | """ 93 | 94 | def __init__(self, config=None): 95 | """ 96 | Sets up the requirements to execute ``goss`` and returns None. 97 | 98 | :param config: An instance of a Molecule config. 99 | :return: None 100 | """ 101 | super(Goss, self).__init__(config) 102 | if config: 103 | self._tests = self._get_tests() 104 | 105 | @property 106 | def name(self): 107 | return "goss" 108 | 109 | @property 110 | def default_options(self): 111 | return {} 112 | 113 | @property 114 | def default_env(self): 115 | return util.merge_dicts(os.environ.copy(), self._config.env) 116 | 117 | def bake(self): 118 | pass 119 | 120 | def execute(self): 121 | if not self.enabled: 122 | msg = "Skipping, verifier is disabled." 123 | LOG.warning(msg) 124 | return 125 | 126 | if not len(self._tests) > 0: 127 | msg = "Skipping, no tests found." 128 | LOG.warning(msg) 129 | return 130 | 131 | msg = "Executing Goss tests found in {}/...".format(self.directory) 132 | LOG.info(msg) 133 | 134 | self._config.provisioner.verify() 135 | 136 | msg = "Verifier completed successfully." 137 | LOG.info(msg) 138 | 139 | def _get_tests(self): 140 | """ 141 | Walk the verifier's directory for tests and returns a list. 142 | 143 | :return: list 144 | """ 145 | return [filename for filename in util.os_walk(self.directory, "test_*.yml")] 146 | 147 | def schema(self): 148 | return { 149 | "verifier": { 150 | "type": "dict", 151 | "schema": { 152 | "name": {"type": "string", "allowed": ["goss"]}, 153 | "options": {"keysrules": {"readonly": True}}, 154 | }, 155 | } 156 | } 157 | 158 | def template_dir(self): 159 | p = os.path.abspath(os.path.join(os.path.dirname(__file__), "cookiecutter")) 160 | return p 161 | -------------------------------------------------------------------------------- /molecule_goss/test/conftest.py: -------------------------------------------------------------------------------- 1 | """Pytest Fixtures.""" 2 | import os 3 | 4 | import pytest 5 | from molecule.test.conftest import random_string, temp_dir # noqa 6 | from molecule import config, logger, util 7 | from molecule.test.conftest import change_dir_to 8 | from molecule.util import run_command 9 | 10 | LOG = logger.get_logger(__name__) 11 | 12 | 13 | @pytest.fixture 14 | def driver_name(): 15 | """Return name of the driver to be tested.""" 16 | return "docker" 17 | 18 | 19 | @pytest.fixture 20 | def molecule_project_directory(): 21 | return os.getcwd() 22 | 23 | 24 | @pytest.fixture 25 | def molecule_directory(): 26 | return config.molecule_directory(molecule_project_directory()) 27 | 28 | 29 | @pytest.fixture 30 | def molecule_scenario_directory(): 31 | return os.path.join(molecule_directory(), "default") 32 | 33 | 34 | @pytest.fixture 35 | def molecule_file(): 36 | return get_molecule_file(molecule_scenario_directory()) 37 | 38 | 39 | @pytest.fixture 40 | def get_molecule_file(path): 41 | return config.molecule_file(path) 42 | 43 | 44 | @pytest.fixture 45 | def with_scenario(request, scenario_to_test, driver_name, scenario_name): 46 | scenario_directory = os.path.join( 47 | os.path.dirname(util.abs_path(__file__)), "scenarios", scenario_to_test 48 | ) 49 | 50 | with change_dir_to(scenario_directory): 51 | yield 52 | if scenario_name: 53 | msg = "CLEANUP: Destroying instances for all scenario(s)" 54 | LOG.info(msg) 55 | cmd = ["molecule", "destroy", "--driver-name", driver_name, "--all"] 56 | assert run_command(cmd).returncode == 0 57 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/centos7/molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | gather_facts: false 5 | roles: 6 | - molecule 7 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/centos7/molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: docker.io/pycontribs/centos:7 9 | pre_build_image: true 10 | provisioner: 11 | name: ansible 12 | # env: 13 | # ANSIBLE_STDOUT_CALLBACK: unixy 14 | verifier: 15 | name: goss 16 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/centos7/molecule/default/tests/test_default.yml: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | --- 4 | file: 5 | /etc/hosts: 6 | exists: true 7 | owner: root 8 | group: root 9 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/centos7/molecule/default/tests/test_install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | file: 3 | /usr/local/bin/goss: 4 | exists: true 5 | owner: root 6 | group: root 7 | mode: "0755" 8 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/centos7/molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: all 4 | become: true 5 | vars: 6 | goss_version: v0.3.13 7 | goss_arch: amd64 8 | goss_bin: /usr/local/bin/goss 9 | goss_sha256sum: eb3522ff9682736ff61e2ad114de227de98debcf8a03ca66fcda3917577313e0. 10 | goss_test_directory: /tmp/molecule/goss 11 | goss_format: documentation 12 | tasks: 13 | - name: Download and install Goss 14 | get_url: 15 | url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" 16 | dest: "{{ goss_bin }}" 17 | sha256sum: "{{ goss_sha256sum }}" 18 | mode: 0755 19 | 20 | - name: Create Molecule directory for test files # noqa 208 21 | file: 22 | path: "{{ goss_test_directory }}" 23 | state: directory 24 | 25 | - name: Find Goss tests on localhost 26 | find: 27 | paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" 28 | patterns: 29 | - "test[-.\\w]*.yml" 30 | - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" 31 | excludes: 32 | - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" 33 | use_regex: true 34 | delegate_to: localhost 35 | register: test_files 36 | changed_when: false 37 | become: false 38 | 39 | - name: debug 40 | debug: 41 | msg: "{{ test_files.files }}" 42 | verbosity: 3 43 | 44 | - name: Copy Goss tests to remote # noqa 208 45 | copy: 46 | src: "{{ item.path }}" 47 | dest: "{{ goss_test_directory }}/{{ item.path | basename }}" 48 | with_items: 49 | - "{{ test_files.files }}" 50 | 51 | - name: Register test files 52 | shell: "ls {{ goss_test_directory }}/test_*.yml" # noqa 301 53 | register: test_files 54 | 55 | - name: Execute Goss tests 56 | command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" # noqa 301 57 | register: test_results 58 | with_items: "{{ test_files.stdout_lines }}" 59 | failed_when: false 60 | 61 | - name: Display details about the Goss results 62 | debug: 63 | msg: "{{ item.stdout_lines }}" 64 | with_items: "{{ test_results.results }}" 65 | 66 | - name: Fail when tests fail 67 | fail: 68 | msg: "Goss failed to validate" 69 | when: item.rc != 0 70 | with_items: "{{ test_results.results }}" 71 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/ubuntu18.04/molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | gather_facts: false 5 | roles: 6 | - molecule 7 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/ubuntu18.04/molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: docker.io/pycontribs/ubuntu:latest 9 | pre_build_image: true 10 | provisioner: 11 | name: ansible 12 | # env: 13 | # ANSIBLE_STDOUT_CALLBACK: unixy 14 | verifier: 15 | name: goss 16 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/ubuntu18.04/molecule/default/tests/test_default.yml: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | --- 4 | file: 5 | /etc/hosts: 6 | exists: true 7 | owner: root 8 | group: root 9 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/ubuntu18.04/molecule/default/tests/test_install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | file: 3 | /usr/local/bin/goss: 4 | exists: true 5 | owner: root 6 | group: root 7 | mode: "0755" 8 | -------------------------------------------------------------------------------- /molecule_goss/test/scenarios/docker/ubuntu18.04/molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: all 4 | become: true 5 | vars: 6 | goss_version: v0.3.13 7 | goss_arch: amd64 8 | goss_bin: /usr/local/bin/goss 9 | goss_sha256sum: eb3522ff9682736ff61e2ad114de227de98debcf8a03ca66fcda3917577313e0. 10 | goss_test_directory: /tmp/molecule/goss 11 | goss_format: documentation 12 | tasks: 13 | - name: Download and install Goss 14 | get_url: 15 | url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" 16 | dest: "{{ goss_bin }}" 17 | sha256sum: "{{ goss_sha256sum }}" 18 | mode: 0755 19 | 20 | - name: Create Molecule directory for test files # noqa 208 21 | file: 22 | path: "{{ goss_test_directory }}" 23 | state: directory 24 | 25 | - name: Find Goss tests on localhost 26 | find: 27 | paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" 28 | patterns: 29 | - "test[-.\\w]*.yml" 30 | - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" 31 | excludes: 32 | - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" 33 | use_regex: true 34 | delegate_to: localhost 35 | register: test_files 36 | changed_when: false 37 | become: false 38 | 39 | - name: debug 40 | debug: 41 | msg: "{{ test_files.files }}" 42 | verbosity: 3 43 | 44 | - name: Copy Goss tests to remote # noqa 208 45 | copy: 46 | src: "{{ item.path }}" 47 | dest: "{{ goss_test_directory }}/{{ item.path | basename }}" 48 | with_items: 49 | - "{{ test_files.files }}" 50 | 51 | - name: Register test files 52 | shell: "ls {{ goss_test_directory }}/test_*.yml" # noqa 301 53 | register: test_files 54 | 55 | - name: Execute Goss tests 56 | command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" # noqa 301 57 | register: test_results 58 | with_items: "{{ test_files.stdout_lines }}" 59 | failed_when: false 60 | 61 | - name: Display details about the Goss results 62 | debug: 63 | msg: "{{ item.stdout_lines }}" 64 | with_items: "{{ test_results.results }}" 65 | 66 | - name: Fail when tests fail 67 | fail: 68 | msg: "Goss failed to validate" 69 | when: item.rc != 0 70 | with_items: "{{ test_results.results }}" 71 | -------------------------------------------------------------------------------- /molecule_goss/test/test_command.py: -------------------------------------------------------------------------------- 1 | """Functional tests.""" 2 | import subprocess 3 | 4 | import pytest 5 | from molecule import logger 6 | from molecule.util import run_command 7 | 8 | 9 | LOG = logger.get_logger(__name__) 10 | 11 | 12 | @pytest.fixture 13 | def scenario_to_test(request): 14 | return request.param 15 | 16 | 17 | @pytest.fixture 18 | def driver_name(request): 19 | return request.param 20 | 21 | 22 | @pytest.fixture 23 | def scenario_name(request): 24 | return request.param 25 | 26 | 27 | def format_result(result: subprocess.CompletedProcess): 28 | """Return friendly representation of completed process run.""" 29 | return ( 30 | f"RC: {result.returncode}\n" 31 | + f"STDOUT: {result.stdout}\n" 32 | + f"STDERR: {result.stderr}\n" 33 | ) 34 | 35 | 36 | def test_command_init_role_goss_verifier(temp_dir): 37 | """Verify that init scenario works.""" 38 | cmd = ["molecule", "init", "role", "test-init", "--verifier-name", "goss"] 39 | assert run_command(cmd).returncode == 0 40 | 41 | 42 | @pytest.mark.extensive 43 | @pytest.mark.parametrize( 44 | "scenario_to_test, driver_name, scenario_name", 45 | [("docker/centos7", "docker", "default")], 46 | # indirect=["scenario_to_test", "driver_name", "scenario_name"], 47 | ) 48 | def test_command_scenario_centos7(scenario_to_test, with_scenario, scenario_name): 49 | cmd = ["molecule", "test", "--scenario-name", scenario_name] 50 | assert run_command(cmd).returncode == 0 51 | 52 | 53 | @pytest.mark.extensive 54 | @pytest.mark.parametrize( 55 | "scenario_to_test, driver_name, scenario_name", 56 | [("docker/ubuntu18.04", "docker", "default")], 57 | # indirect=["scenario_to_test", "driver_name", "scenario_name"], 58 | ) 59 | def test_command_scenario_ubuntu18(scenario_to_test, with_scenario, scenario_name): 60 | cmd = ["molecule", "test", "--scenario-name", scenario_name] 61 | assert run_command(cmd).returncode == 0 62 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | python_version = 3.6 3 | color_output = True 4 | error_summary = True 5 | disallow_untyped_calls=True 6 | warn_redundant_casts=True 7 | 8 | # 3rd party ignores, to remove once they add hints 9 | [mypy-molecule.*] 10 | ignore_missing_imports = True 11 | 12 | [mypy-docker] 13 | ignore_missing_imports = True 14 | 15 | [mypy-pytest] 16 | ignore_missing_imports = True 17 | 18 | [mypy-setuptools] 19 | ignore_missing_imports = True 20 | 21 | [mypy-sh] 22 | ignore_missing_imports = True 23 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "pip >= 19.3.1", 4 | "setuptools >= 42", 5 | "setuptools_scm[toml] >= 3.5.0", 6 | "setuptools_scm_git_archive >= 1.1", 7 | "wheel >= 0.33.6", 8 | ] 9 | build-backend = "setuptools.build_meta" 10 | 11 | [tool.black] 12 | skip-string-normalization = false 13 | 14 | [tool.isort] 15 | profile = "black" 16 | float_to_top = true 17 | known_third_party = [ 18 | "molecule" 19 | ] 20 | 21 | [tool.setuptools_scm] 22 | local_scheme = "no-local-version" 23 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [aliases] 2 | dists = clean --all sdist bdist_wheel 3 | 4 | 5 | [metadata] 6 | name = molecule-goss 7 | url = https://github.com/ansible-community/molecule-goss 8 | project_urls = 9 | Bug Tracker = https://github.com/ansible-community/molecule-goss/issues 10 | Release Management = https://github.com/ansible-community/molecule-goss/releases 11 | CI = https://github.com/ansible-community/molecule-goss/actions 12 | Code of Conduct = https://docs.ansible.com/ansible/latest/community/code_of_conduct.html 13 | Documentation = https://molecule.readthedocs.io 14 | Discussions = https://github.com/ansible-community/molecule/discussions 15 | Source Code = https://github.com/ansible-community/molecule-goss 16 | description = Goss Molecule Plugin :: run molecule tests with Goss as verifier 17 | long_description = file: README.rst 18 | long_description_content_type = text/x-rst 19 | author = Ansible by Red Hat 20 | author_email = info@ansible.com 21 | maintainer = Ansible by Red Hat 22 | maintainer_email = info@ansible.com 23 | license = MIT 24 | license_file = LICENSE 25 | classifiers = 26 | Development Status :: 5 - Production/Stable 27 | 28 | Environment :: Console 29 | 30 | Intended Audience :: Developers 31 | Intended Audience :: Information Technology 32 | Intended Audience :: System Administrators 33 | 34 | License :: OSI Approved :: MIT License 35 | 36 | Natural Language :: English 37 | 38 | Operating System :: OS Independent 39 | 40 | Programming Language :: Python :: 3 41 | Programming Language :: Python :: 3.6 42 | Programming Language :: Python :: 3.7 43 | Programming Language :: Python :: 3.8 44 | 45 | Topic :: System :: Systems Administration 46 | Topic :: Utilities 47 | keywords = 48 | ansible 49 | roles 50 | testing 51 | molecule 52 | plugin 53 | goss 54 | verifier 55 | 56 | [options] 57 | use_scm_version = True 58 | python_requires = >=3.6 59 | packages = find: 60 | include_package_data = True 61 | zip_safe = False 62 | 63 | # These are required during `setup.py` run: 64 | setup_requires = 65 | setuptools_scm >= 1.15.0 66 | setuptools_scm_git_archive >= 1.0 67 | 68 | # These are required in actual runtime: 69 | install_requires = 70 | # molecule plugins are not allowed to mention Ansible as a direct dependency 71 | molecule >= 3.2.0 72 | pyyaml >= 5.1, < 6 73 | 74 | [options.extras_require] 75 | docs = 76 | simplejson 77 | Sphinx 78 | sphinx_ansible_theme >= 0.2.2 79 | lint = 80 | pre-commit >= 1.21.0 81 | test = 82 | molecule[test] 83 | pytest-helpers-namespace 84 | 85 | [options.entry_points] 86 | molecule.verifier = 87 | goss = molecule_goss.goss:Goss 88 | 89 | [options.packages.find] 90 | where = . 91 | 92 | [tool:pytest] 93 | addopts = --doctest-modules --durations 10 --color=yes 94 | doctest_optionflags = ALLOW_UNICODE ELLIPSIS 95 | norecursedirs = dist doc build .tox .eggs 96 | # testpaths = molecule/test/ 97 | filterwarnings = 98 | # treat warnings as errors unless we add them below 99 | error 100 | # ignore::UserWarning 101 | markers = 102 | extensive: marks tests that we want to skip by default, as they are indirectly covered by other tests 103 | 104 | [flake8] 105 | # do not add excludes for files in repo 106 | exclude = .venv/,.tox/,dist/,build/,.eggs/ 107 | format = pylint 108 | # E203: https://github.com/python/black/issues/315 109 | ignore = E741,W503,W504,H,E501,E203,D102 110 | # TODO(ssbarnea): remove temporary skips one by one: 111 | # [D102] Missing docstring in public method 112 | # [D104] Missing docstring in public package 113 | # 88 is official black default: 114 | max-line-length = 88 115 | per-file-ignores = 116 | docs/conf.py: D 117 | molecule/test/*: D100,D103,D104 118 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import site 5 | import sys 6 | 7 | import setuptools 8 | 9 | # See https://github.com/pypa/pip/issues/7953 10 | site.ENABLE_USER_SITE = "--user" in sys.argv[1:] 11 | 12 | 13 | if __name__ == "__main__": 14 | setuptools.setup( 15 | use_scm_version={"local_scheme": "no-local-version"}, 16 | setup_requires=["setuptools_scm[toml]>=3.5.0"], 17 | ) 18 | -------------------------------------------------------------------------------- /tools/test-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | # Used by Zuul CI to perform extra bootstrapping 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 6 | 7 | # Bumping system tox because version from CentOS 7 is too old 8 | # We are not using pip --user due to few bugs in tox role which does not allow 9 | # us to override how is called. Once these are addressed we will switch back 10 | # non-sudo 11 | command -v python3 python 12 | 13 | PYTHON=$(command -v python3 python|head -n1) 14 | PKG_CMD=$(command -v dnf yum|head -n1) 15 | 16 | sudo $PYTHON -m pip install -U tox "zipp<0.6.0;python_version=='2.7'" 17 | 18 | # Install latest goss version to /usr/local/bin 19 | curl -fsSL https://goss.rocks/install | sudo sh 20 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # For more information about tox, see https://tox.readthedocs.io/en/latest/ 2 | [tox] 3 | minversion = 3.9.0 4 | envlist = 5 | lint 6 | packaging 7 | py{36,37,38,39} 8 | py-{36,37,38,39}-devel 9 | 10 | skip_missing_interpreters = True 11 | isolated_build = True 12 | 13 | requires = 14 | # 2020-resolver 15 | pip >= 20.2.4 16 | 17 | [testenv] 18 | description = 19 | Unit testing 20 | usedevelop = True 21 | extras = 22 | ansible 23 | lint 24 | test 25 | commands = 26 | ansibledevel: ansible-galaxy install git+https://github.com/ansible-collections/community.general.git 27 | # failsafe as pip may install incompatible dependencies 28 | pip check 29 | # use cookiecutter to deploy the functional test verify playbooks 30 | cookiecutter -f molecule_goss/cookiecutter/ --output-dir molecule_goss/test/scenarios/docker/centos7/ --no-input 31 | cookiecutter -f molecule_goss/cookiecutter/ --output-dir molecule_goss/test/scenarios/docker/ubuntu18.04/ --no-input 32 | # failsafe for preventing changes that may break pytest collection 33 | python -m pytest -p no:cov --collect-only 34 | python -m pytest {posargs:-l} 35 | setenv = 36 | ANSIBLE_FORCE_COLOR={env:ANSIBLE_FORCE_COLOR:1} 37 | ANSIBLE_INVENTORY={toxinidir}/tests/hosts.ini 38 | ANSIBLE_CONFIG={toxinidir}/ansible.cfg 39 | ANSIBLE_NOCOWS=1 40 | ANSIBLE_RETRY_FILES_ENABLED=0 41 | ANSIBLE_STDOUT_CALLBACK={env:ANSIBLE_STDOUT_CALLBACK:debug} 42 | ANSIBLE_VERBOSITY={env:ANSIBLE_VERBOSITY:0} 43 | PIP_DISABLE_PIP_VERSION_CHECK=1 44 | PY_COLORS={env:PY_COLORS:1} 45 | # pip: Avoid 2020-01-01 warnings: https://github.com/pypa/pip/issues/6207 46 | PYTHONWARNINGS=ignore:DEPRECATION::pip._internal.cli.base_command 47 | PYTHONDONTWRITEBYTECODE=1 48 | # This should pass these args to molecule, no effect here as this is the default 49 | # but it validates that it accepts extra params. 50 | MOLECULE_NO_LOG=0 51 | deps = 52 | devel: ansible>=2.10.3,<2.11 53 | py{36,37,38,39}: molecule[ansible,test] 54 | py{36,37,38,39}-{devel}: git+https://github.com/ansible-community/molecule.git@master#egg=molecule[ansible,test] 55 | dockerfile: ansible>=2.9.12 56 | cookiecutter 57 | molecule-docker 58 | docker>=4.3.1 59 | passenv = 60 | CI 61 | CURL_CA_BUNDLE 62 | DOCKER_* 63 | HOME 64 | PYTEST_OPTIONS 65 | REQUESTS_CA_BUNDLE 66 | SSH_AUTH_SOCK 67 | SSL_CERT_FILE 68 | TOXENV 69 | TRAVIS 70 | TRAVIS_* 71 | TWINE_* 72 | VAGRANT_HOME 73 | whitelist_externals = 74 | bash 75 | twine 76 | pytest 77 | pre-commit 78 | 79 | [testenv:packaging] 80 | usedevelop = false 81 | skip_install = true 82 | deps = 83 | collective.checkdocs >= 0.2 84 | pep517 >= 0.5.0 85 | twine >= 2.0.0 86 | commands = 87 | bash -c "rm -rf {toxinidir}/dist/ {toxinidir}/build/ && mkdir -p {toxinidir}/dist/" 88 | python -m pep517.build \ 89 | --source \ 90 | --binary \ 91 | --out-dir {toxinidir}/dist/ \ 92 | {toxinidir} 93 | twine check dist/* 94 | 95 | [testenv:devel] 96 | description= Unit testing using master branches of molecule and ansible 97 | extras = test 98 | commands = 99 | {[testenv]commands} 100 | deps = 101 | git+https://github.com/ansible/ansible.git#egg=ansible 102 | git+https://github.com/ansible-community/molecule#egg=molecule 103 | 104 | [testenv:lint] 105 | description = Performs linting, style checks 106 | skip_install = true 107 | deps = 108 | pre-commit 109 | commands = 110 | pre-commit run -a 111 | 112 | [testenv:upload] 113 | description = Builds the packages and uploads them to https://pypi.org 114 | envdir={toxworkdir}/dist 115 | deps= 116 | {[testenv:packaging]deps} 117 | commands = 118 | {[testenv:packaging]commands} 119 | twine upload --verbose dist/* 120 | --------------------------------------------------------------------------------