diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 001e2d7..842d854 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -1,20 +1,11 @@ -# README FIRST -# 1. replace "NAMESPACE" and "COLLECTION_NAME" with the correct name in the env section (e.g. with 'community' and 'mycollection') -# 2. If you don't have unit tests remove that section -# 3. If your collection depends on other collections ensure they are installed, see "Install collection dependencies" -# If you need help please ask in #ansible-devel on Freenode IRC - name: CI on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests push: pull_request: - # Uncomment the following two lines to run CI once per day (at 06:00 UTC) - # schedule: - # - cron: '0 6 * * *' -env: - NAMESPACE: NAMESPACE - COLLECTION_NAME: COLLECTION_NAME + # Run CI once per day (at 06:00 UTC) + schedule: + - cron: '0 6 * * *' jobs: @@ -30,19 +21,19 @@ jobs: ansible: # It's important that Sanity is tested against all stable-X.Y branches # Testing against `devel` may fail as new tests are added. - # - stable-2.9 # Only if your collection supports Ansible 2.9 + - stable-2.9 - stable-2.10 - devel runs-on: ubuntu-latest steps: # ansible-test requires the collection to be in a directory in the form - # .../ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/ + # .../ansible_collections/community/routeros/ - name: Check out code uses: actions/checkout@v2 with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + path: ansible_collections/community/routeros - name: Set up Python uses: actions/setup-python@v2 @@ -55,12 +46,15 @@ jobs: - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + - name: Install collection dependencies + run: ansible-galaxy collection install ansible.netcommon -p . + # run ansible-test sanity inside of Docker. # The docker container has all the pinned dependencies that are required # and all python versions ansible supports. - name: Run sanity tests run: ansible-test sanity --docker -v --color - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + working-directory: ./ansible_collections/community/routeros ### # Unit tests (OPTIONAL) @@ -75,7 +69,7 @@ jobs: fail-fast: true matrix: ansible: - # - stable-2.9 # Only if your collection supports Ansible 2.9 + - stable-2.9 - stable-2.10 - devel python: @@ -94,32 +88,30 @@ jobs: - name: Check out code uses: actions/checkout@v2 with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + path: ansible_collections/community/routeros - name: Set up Python ${{ matrix.ansible }} uses: actions/setup-python@v2 with: - python-version: ${{ matrix.python }} + python-version: 3.8 - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - # OPTIONAL If your unit test requires Python libraries from other collections - # Install them like this - name: Install collection dependencies run: ansible-galaxy collection install ansible.netcommon -p . # Run the unit tests - name: Run unit test run: ansible-test units -v --color --python ${{ matrix.python }} --docker --coverage - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + working-directory: ./ansible_collections/community/routeros # ansible-test support producing code coverage date - name: Generate coverage report run: ansible-test coverage xml -v --requirements --group-by command --group-by version - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + working-directory: ./ansible_collections/community/routeros - # See the reports at https://codecov.io/gh/ansible_collections/GITHUBORG/REPONAME + # See the reports at https://codecov.io/gh/ansible_collections/ansible-collections/community.routeros - uses: codecov/codecov-action@v1 with: fail_ci_if_error: false @@ -134,58 +126,56 @@ jobs: # multiple versions see the following for an example: # https://github.com/ansible-collections/community.zabbix/tree/master/.github/workflows - integration: - runs-on: ubuntu-latest - name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}}) - strategy: - fail-fast: false - matrix: - ansible: - # - stable-2.9 # Only if your collection supports Ansible 2.9 - - stable-2.10 - - devel - python: - - 2.6 - - 2.7 - - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9 - exclude: - - ansible: stable-2.9 - python: 3.9 - - steps: - - name: Check out code - uses: actions/checkout@v2 - with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - - name: Set up Python ${{ matrix.ansible }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - # OPTIONAL If your integration test requires Python libraries or modules from other collections - # Install them like this - - name: Install collection dependencies - run: ansible-galaxy collection install ansible.netcommon -p . - - # Run the integration tests - - name: Run integration test - run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --coverage - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - # ansible-test support producing code coverage date - - name: Generate coverage report - run: ansible-test coverage xml -v --requirements --group-by command --group-by version - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - # See the reports at https://codecov.io/gh/ansible_collections/GITHUBORG/REPONAME - - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: false +# integration: +# runs-on: ubuntu-latest +# name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}}) +# strategy: +# fail-fast: false +# matrix: +# ansible: +# - stable-2.9 +# - stable-2.10 +# - devel +# python: +# - 2.6 +# - 2.7 +# - 3.5 +# - 3.6 +# - 3.7 +# - 3.8 +# - 3.9 +# exclude: +# - ansible: stable-2.9 +# python: 3.9 +# +# steps: +# - name: Check out code +# uses: actions/checkout@v2 +# with: +# path: ansible_collections/community/routeros +# +# - name: Set up Python ${{ matrix.ansible }} +# uses: actions/setup-python@v2 +# with: +# python-version: 3.8 +# +# - name: Install ansible-base (${{ matrix.ansible }}) +# run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check +# +# - name: Install collection dependencies +# run: ansible-galaxy collection install ansible.netcommon -p . +# +# # Run the integration tests +# - name: Run integration test +# run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --coverage +# working-directory: ./ansible_collections/community/routeros +# +# # ansible-test support producing code coverage date +# - name: Generate coverage report +# run: ansible-test coverage xml -v --requirements --group-by command --group-by version +# working-directory: ./ansible_collections/community/routeros +# +# # See the reports at https://codecov.io/gh/ansible_collections/ansible-collections/community.routeros +# - uses: codecov/codecov-action@v1 +# with: +# fail_ci_if_error: false diff --git a/LICENSE b/COPYING similarity index 100% rename from LICENSE rename to COPYING diff --git a/README.md b/README.md index 0ddb655..22726a5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ -# collection_template -You can build a new repository for an Ansible Collection using this template by following [Creating a repository from a template](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template). This README.md contains recommended headings for your collection README.md, with comments describing what each section should contain. Once you have created your collection repository, delete this paragraph and the title above it from your README.md. - -# Foo Collection - -[![CI](https://github.com/ansible-collections/REPONAMEHERE/workflows/CI/badge.svg?event=push)](https://github.com/ansible-collections/REPONAMEHERE/actions) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/REPONAMEHERE)](https://codecov.io/gh/ansible-collections/REPONAMEHERE) +# Community RouterOS Collection +[![CI](https://github.com/ansible-collections/community.routeros/workflows/CI/badge.svg?event=push)](https://github.com/ansible-collections/community.routeros/actions) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.routeros)](https://codecov.io/gh/ansible-collections/community.routeros) @@ -59,4 +55,4 @@ See the [changelog](https://github.com/ansible-collections/REPONAMEHERE/tree/mai GNU General Public License v3.0 or later. -See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. +See [COPYING](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 08c3ba7..8f014ed 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -4,6 +4,7 @@ changes_file: changelog.yaml changes_format: combined keep_fragments: false mention_ancestor: true +flatmap: true new_plugins_after_name: removed_features notesdir: fragments prelude_section_name: release_summary @@ -25,5 +26,4 @@ sections: - Bugfixes - - known_issues - Known Issues -title: CHANGE THIS IN changelogs/config.yaml! -trivial_section_name: trivial +title: Community RouterOS diff --git a/galaxy.yml b/galaxy.yml index 8f4180d..5a35e9e 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,23 +1,24 @@ # See https://docs.ansible.com/ansible/latest/dev_guide/collections_galaxy_meta.html namespace: community -name: FIXME +name: routeros version: 0.1.0 readme: README.md authors: - - YOUR NAME (github.com/YOURGITHUB) -description: null + - Egor Zaitsev (github.com/heuels) + - Nikolay Dachev (github.com/NikolayDachev) +description: Modules for MikroTik RouterOS license_file: COPYING tags: -# tags so people can search for collections https://galaxy.ansible.com/search -# tags are all lower-case, no spaces, no dashes. - - example1 - - example2 -repository: https://github.com/ansible-collections/community.REPO_NAME -#documentation: https://github.com/ansible-collection-migration/community.REPO_NAME/tree/main/docs -homepage: https://github.com/ansible-collections/community.REPO_NAME -issues: https://github.com/ansible-collections/community.REPO_NAME/issues + - network + - mikrotik + - routeros +dependencies: + ansible.netcommon: '>=1.0.0' +repository: https://github.com/ansible-collections/community.routeros +#documentation: https://github.com/ansible-collection-migration/community.routeros/tree/main/docs +homepage: https://github.com/ansible-collections/community.routeros +issues: https://github.com/ansible-collections/community.routeros/issues build_ignore: -# https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#ignoring-files-and-folders - .gitignore - changelogs/.plugin-cache.yaml diff --git a/tests/requirements.yml b/tests/requirements.yml new file mode 100644 index 0000000..a218740 --- /dev/null +++ b/tests/requirements.yml @@ -0,0 +1,4 @@ +integration_tests_dependencies: +- ansible.netcommon +unit_tests_dependencies: +- ansible.netcommon diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt new file mode 100644 index 0000000..9d5934b --- /dev/null +++ b/tests/sanity/ignore-2.10.txt @@ -0,0 +1,5 @@ +plugins/modules/command.py validate-modules:doc-missing-type +plugins/modules/command.py validate-modules:parameter-list-no-elements +plugins/modules/command.py validate-modules:parameter-type-not-in-doc +plugins/modules/facts.py validate-modules:parameter-list-no-elements +plugins/modules/facts.py validate-modules:parameter-type-not-in-doc diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt new file mode 100644 index 0000000..9d5934b --- /dev/null +++ b/tests/sanity/ignore-2.11.txt @@ -0,0 +1,5 @@ +plugins/modules/command.py validate-modules:doc-missing-type +plugins/modules/command.py validate-modules:parameter-list-no-elements +plugins/modules/command.py validate-modules:parameter-type-not-in-doc +plugins/modules/facts.py validate-modules:parameter-list-no-elements +plugins/modules/facts.py validate-modules:parameter-type-not-in-doc diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt new file mode 100644 index 0000000..c1e40c7 --- /dev/null +++ b/tests/sanity/ignore-2.9.txt @@ -0,0 +1,3 @@ +plugins/modules/command.py validate-modules:doc-missing-type +plugins/modules/command.py validate-modules:parameter-type-not-in-doc +plugins/modules/facts.py validate-modules:parameter-type-not-in-doc diff --git a/tests/unit/compat/__init__.py b/tests/unit/compat/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/compat/builtins.py b/tests/unit/compat/builtins.py new file mode 100644 index 0000000..f60ee67 --- /dev/null +++ b/tests/unit/compat/builtins.py @@ -0,0 +1,33 @@ +# (c) 2014, Toshio Kuratomi +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +# +# Compat for python2.7 +# + +# One unittest needs to import builtins via __import__() so we need to have +# the string that represents it +try: + import __builtin__ +except ImportError: + BUILTINS = 'builtins' +else: + BUILTINS = '__builtin__' diff --git a/tests/unit/compat/mock.py b/tests/unit/compat/mock.py new file mode 100644 index 0000000..0972cd2 --- /dev/null +++ b/tests/unit/compat/mock.py @@ -0,0 +1,122 @@ +# (c) 2014, Toshio Kuratomi +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python3.x's unittest.mock module +''' +import sys + +# Python 2.7 + +# Note: Could use the pypi mock library on python3.x as well as python2.x. It +# is the same as the python3 stdlib mock library + +try: + # Allow wildcard import because we really do want to import all of mock's + # symbols into this compat shim + # pylint: disable=wildcard-import,unused-wildcard-import + from unittest.mock import * +except ImportError: + # Python 2 + # pylint: disable=wildcard-import,unused-wildcard-import + try: + from mock import * + except ImportError: + print('You need the mock library installed on python2.x to run tests') + + +# Prior to 3.4.4, mock_open cannot handle binary read_data +if sys.version_info >= (3,) and sys.version_info < (3, 4, 4): + file_spec = None + + def _iterate_read_data(read_data): + # Helper for mock_open: + # Retrieve lines from read_data via a generator so that separate calls to + # readline, read, and readlines are properly interleaved + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: + # If the last line ended in a newline, the list comprehension will have an + # extra entry that's just a newline. Remove this. + data_as_list = data_as_list[:-1] + else: + # If there wasn't an extra newline by itself, then the file being + # emulated doesn't have a newline to end the last line remove the + # newline that our naive format() added + data_as_list[-1] = data_as_list[-1][:-1] + + for line in data_as_list: + yield line + + def mock_open(mock=None, read_data=''): + """ + A helper function to create a mock to replace the use of `open`. It works + for `open` called directly or used as a context manager. + + The `mock` argument is the mock object to configure. If `None` (the + default) then a `MagicMock` will be created for you, with the API limited + to methods or attributes available on standard file handles. + + `read_data` is a string for the `read` methoddline`, and `readlines` of the + file handle to return. This is an empty string by default. + """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return type(read_data)().join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + global file_spec + if file_spec is None: + import _io + file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) + + if mock is None: + mock = MagicMock(name='open', spec=open) + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + + mock.return_value = handle + return mock diff --git a/tests/unit/compat/unittest.py b/tests/unit/compat/unittest.py new file mode 100644 index 0000000..98f08ad --- /dev/null +++ b/tests/unit/compat/unittest.py @@ -0,0 +1,38 @@ +# (c) 2014, Toshio Kuratomi +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python2.7's unittest module +''' + +import sys + +# Allow wildcard import because we really do want to import all of +# unittests's symbols into this compat shim +# pylint: disable=wildcard-import,unused-wildcard-import +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + from unittest2 import * + except ImportError: + print('You need unittest2 installed on python2.6.x to run tests') +else: + from unittest import * diff --git a/tests/unit/plugins/modules/utils.py b/tests/unit/plugins/modules/utils.py new file mode 100644 index 0000000..89b4aa2 --- /dev/null +++ b/tests/unit/plugins/modules/utils.py @@ -0,0 +1,50 @@ +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import json + +from ansible_collections.community.routeros.tests.unit.compat import unittest +from ansible_collections.community.routeros.tests.unit.compat.mock import patch +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + + +def set_module_args(args): + if '_ansible_remote_tmp' not in args: + args['_ansible_remote_tmp'] = '/tmp' + if '_ansible_keep_remote_files' not in args: + args['_ansible_keep_remote_files'] = False + + args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + +class ModuleTestCase(unittest.TestCase): + + def setUp(self): + self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json) + self.mock_module.start() + self.mock_sleep = patch('time.sleep') + self.mock_sleep.start() + set_module_args({}) + self.addCleanup(self.mock_module.stop) + self.addCleanup(self.mock_sleep.stop) diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt new file mode 100644 index 0000000..eac8a96 --- /dev/null +++ b/tests/unit/requirements.txt @@ -0,0 +1,4 @@ +unittest2 ; python_version <= '2.6' + +# requirements for api module +librouteros ; python_version >= '3.6'