From a88f4c804b147136f9164e571408e90a649532e1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 12 Aug 2021 08:53:21 +0200 Subject: [PATCH 001/365] Fix sanity failures (#43) * Fix sanity failures. * Add changelog fragment. --- changelogs/fragments/43-sanity.yml | 2 ++ plugins/cliconf/routeros.py | 2 +- tests/unit/plugins/modules/test_facts.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/43-sanity.yml diff --git a/changelogs/fragments/43-sanity.yml b/changelogs/fragments/43-sanity.yml new file mode 100644 index 0000000..5c918d1 --- /dev/null +++ b/changelogs/fragments/43-sanity.yml @@ -0,0 +1,2 @@ +bugfixes: +- "routeros cliconf plugin - adjust function signature that was modified in Ansible after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43)." diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py index 6c49373..f46b3a0 100644 --- a/plugins/cliconf/routeros.py +++ b/plugins/cliconf/routeros.py @@ -65,7 +65,7 @@ class Cliconf(CliconfBase): return device_info - def get_config(self, source='running', format='text', flags=None): + def get_config(self, source='running', flags=None, format=None): return def edit_config(self, command): diff --git a/tests/unit/plugins/modules/test_facts.py b/tests/unit/plugins/modules/test_facts.py index ea111df..9552047 100644 --- a/tests/unit/plugins/modules/test_facts.py +++ b/tests/unit/plugins/modules/test_facts.py @@ -43,7 +43,7 @@ class TestRouterosFactsModule(TestRouterosModule): output = list() for command in commands: - filename = str(command).split(' | ')[0].replace(' ', '_') + filename = str(command).split(' | ', 1)[0].replace(' ', '_') output.append(load_fixture('facts%s' % filename)) return output From 48c7920072590c59b4052fd63e3fc8d57b6325ce Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 9 Sep 2021 22:19:57 +0200 Subject: [PATCH 002/365] Improve split handling. (#47) --- changelogs/fragments/47-api-split.yml | 3 +++ plugins/modules/api.py | 16 +++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/47-api-split.yml diff --git a/changelogs/fragments/47-api-split.yml b/changelogs/fragments/47-api-split.yml new file mode 100644 index 0000000..10e8033 --- /dev/null +++ b/changelogs/fragments/47-api-split.yml @@ -0,0 +1,3 @@ +bugfixes: + - "api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47)." + - "api - when converting result lists to dictionaries, no longer removes second ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47)." diff --git a/plugins/modules/api.py b/plugins/modules/api.py index c25e6c8..6288834 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -321,12 +321,14 @@ class ROS_api_module: self.where = None self.query = self.module.params['query'] if self.query: - if 'WHERE' in self.query: - split = self.query.split('WHERE') - self.query = self.list_remove_empty(split[0].split(' ')) - self.where = self.list_remove_empty(split[1].split(' ')) - else: - self.query = self.list_remove_empty(self.module.params['query'].split(' ')) + self.query = self.list_remove_empty(self.query.split(' ')) + try: + idx = self.query.index('WHERE') + self.where = self.query[idx + 1:] + self.query = self.query[:idx] + except ValueError: + # Raised when WHERE has not been found + pass self.result = dict( message=[]) @@ -358,7 +360,7 @@ class ROS_api_module: for p in ldict: if '=' not in p: self.errors("missing '=' after '%s'" % p) - p = p.split('=') + p = p.split('=', 1) if p[1]: dict[p[0]] = p[1] return dict From f99202812af08f604f703d233a43834298ba8916 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 24 Sep 2021 18:45:56 +0200 Subject: [PATCH 003/365] Prepare ansible-core devel branch version bump that is planned for later today. --- tests/sanity/ignore-2.13.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/sanity/ignore-2.13.txt diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt new file mode 100644 index 0000000..9d5934b --- /dev/null +++ b/tests/sanity/ignore-2.13.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 From f432b1fa07df4ab8ac4cc0daaa42575858cf01c4 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 28 Sep 2021 15:35:05 +0200 Subject: [PATCH 004/365] Update CI matrix to include ansible-core's stable-2.12 branch (#52) * Update CI matrix to include ansible-core's stable-2.12 branch. * Adjust README. --- .github/workflows/ansible-test.yml | 76 +----------------------------- README.md | 2 +- 2 files changed, 3 insertions(+), 75 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index ca6264c..9a00a3b 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -24,6 +24,7 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 + - stable-2.12 - devel runs-on: ubuntu-latest steps: @@ -75,6 +76,7 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 + - stable-2.12 - devel steps: @@ -110,77 +112,3 @@ jobs: - uses: codecov/codecov-action@v1 with: fail_ci_if_error: false - -### -# Integration tests (RECOMMENDED) -# -# https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html - - -# If the application you are testing is available as a docker container and you want to test -# 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 -# - stable-2.10 -# - stable-2.11 -# - devel -# python: -# - 2.6 -# - 2.7 -# - 3.5 -# - 3.6 -# - 3.7 -# - 3.8 -# - 3.9 -# - "3.10" -# exclude: -# - ansible: stable-2.9 -# python: 3.9 -# - ansible: stable-2.9 -# python: "3.10" -# - ansible: stable-2.10 -# python: "3.10" -# - ansible: stable-2.11 -# python: "3.10" -# -# 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: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon -# # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) -# # 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/README.md b/README.md index bbedf3c..7c8417c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ You can find [documentation for the modules and plugins in this collection here] ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10 and ansible-core 2.11 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11 and ansible-core 2.12 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements From 5042905471bee3490f6ae4006957e49f35c6e132 Mon Sep 17 00:00:00 2001 From: Akim Lindberg <44138907+akimrx@users.noreply.github.com> Date: Wed, 29 Sep 2021 16:02:28 +0300 Subject: [PATCH 005/365] fix(api): fixed a bug when splitting the argument string (#45) * fix(api): fixed a bug when splitting the argument string * fix(api): added the shlex module for splitting * fix(api): added the shlex module for splitting * fix(api): moved shlex.split to self method split_params * Fix indentation. * Implement custom splitting algorithm. * Raise AssertionError in case of internal error. * Update plugins/modules/api.py this is correct thanks ! Co-authored-by: Felix Fontein Co-authored-by: Felix Fontein Co-authored-by: Nikolay Dachev --- changelogs/fragments/45-api-split.yml | 2 + plugins/modules/api.py | 109 +++++++++++++++++++++++-- tests/unit/plugins/modules/test_api.py | 30 +++++++ 3 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/45-api-split.yml diff --git a/changelogs/fragments/45-api-split.yml b/changelogs/fragments/45-api-split.yml new file mode 100644 index 0000000..2d525cb --- /dev/null +++ b/changelogs/fragments/45-api-split.yml @@ -0,0 +1,2 @@ +breaking_changes: + - "api - splitting commands no longer uses a naive split by whitespace, but a more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45)." diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 6288834..93ea250 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -258,7 +258,7 @@ message: from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import missing_required_lib -from ansible.module_utils.common.text.converters import to_native +from ansible.module_utils.common.text.converters import to_native, to_bytes import ssl import traceback @@ -274,6 +274,95 @@ except Exception as e: LIB_IMP_ERR = traceback.format_exc() +class ParseError(Exception): + pass + + +ESCAPE_SEQUENCES = { + b'"': b'"', + b'\\': b'\\', + b'?': b'?', + b'$': b'$', + b'_': b'_', + b'a': b'\a', + b'b': b'\b', + b'f': b'\xFF', + b'n': b'\n', + b'r': b'\r', + b't': b'\t', + b'v': b'\v', +} + +ESCAPE_DIGITS = b'0123456789ABCDEF' + + +def split_routeros(line): + line = to_bytes(line) + result = [] + current = [] + index = 0 + length = len(line) + # States: + # 0 = outside param + # 1 = param before '=' + # 2 = param after '=' without quote + # 3 = param after '=' with quote + state = 0 + while index < length: + ch = line[index:index + 1] + index += 1 + if state == 0 and ch == b' ': + pass + elif state in (1, 2) and ch == b' ': + state = 0 + result.append(b''.join(current)) + current = [] + elif ch == b'=' and state == 1: + state = 2 + current.append(ch) + if index + 1 < length and line[index:index + 1] == b'"': + state = 3 + index += 1 + elif ch == b'"': + if state == 3: + state = 0 + result.append(b''.join(current)) + current = [] + if index + 1 < length and line[index:index + 1] != b' ': + raise ParseError('Ending \'"\' must be followed by space or end of string') + else: + raise ParseError('\'"\' must follow \'=\'') + elif ch == b'\\': + if index + 1 == length: + raise ParseError('\'\\\' must not be at the end of the line') + ch = line[index:index + 1] + index += 1 + if ch in ESCAPE_SEQUENCES: + current.append(ch) + else: + d1 = ESCAPE_DIGITS.find(ch) + if d1 < 0: + raise ParseError('Invalid escape sequence \'\\{0}\''.format(ch)) + if index + 1 == length: + raise ParseError('Hex escape sequence cut off at end of line') + ch2 = line[index:index + 1] + d2 = ESCAPE_DIGITS.find(ch2) + index += 1 + if d2 < 0: + raise ParseError('Invalid hex escape sequence \'\\{0}{1}\''.format(ch, ch2)) + result.append(chr(d1 * 16 + d2)) + else: + current.append(ch) + if state == 0: + state = 1 + if state in (1, 2): + if current: + result.append(b''.join(current)) + elif state == 3: + raise ParseError('Unexpected end of string during escaped parameter') + return [to_native(part) for part in result] + + class ROS_api_module: def __init__(self): module_args = dict( @@ -312,7 +401,7 @@ class ROS_api_module: self.module.params['ca_path'], ) - self.path = self.list_remove_empty(self.module.params['path'].split(' ')) + self.path = self.module.params['path'].split() self.add = self.module.params['add'] self.remove = self.module.params['remove'] self.update = self.module.params['update'] @@ -321,7 +410,7 @@ class ROS_api_module: self.where = None self.query = self.module.params['query'] if self.query: - self.query = self.list_remove_empty(self.query.split(' ')) + self.query = self.list_remove_empty(self.split_params(self.query)) try: idx = self.query.index('WHERE') self.where = self.query[idx + 1:] @@ -365,6 +454,14 @@ class ROS_api_module: dict[p[0]] = p[1] return dict + def split_params(self, params): + if not isinstance(params, str): + raise AssertionError('Parameters can only be a string, received %s' % type(params)) + try: + return split_routeros(params) + except ParseError as e: + self.module.fail_json(msg=to_native(e)) + def api_add_path(self, api, path): api_path = api.path() for p in path: @@ -380,7 +477,7 @@ class ROS_api_module: self.errors(e) def api_add(self): - param = self.list_to_dic(self.add.split(' ')) + param = self.list_to_dic(self.split_params(self.add)) try: self.result['message'].append("added: .id= %s" % self.api_path.add(**param)) @@ -397,7 +494,7 @@ class ROS_api_module: self.errors(e) def api_update(self): - param = self.list_to_dic(self.update.split(' ')) + param = self.list_to_dic(self.split_params(self.update)) if '.id' not in param.keys(): self.errors("missing '.id' for %s" % param) try: @@ -448,7 +545,7 @@ class ROS_api_module: def api_arbitrary(self): param = {} - self.arbitrary = self.arbitrary.split(' ') + self.arbitrary = self.split_params(self.arbitrary) arb_cmd = self.arbitrary[0] if len(self.arbitrary) > 1: param = self.list_to_dic(self.arbitrary[1:]) diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index cabb918..0eabc04 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -288,3 +288,33 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) + + +TEST_SPLIT_ROUTEROS = [ + ('', []), + (' ', []), + (r'a b c', ['a', 'b', 'c']), + (r'a=b c d=e', ['a=b', 'c', 'd=e']), + (r'a="b f" c d=e', ['a=b f', 'c', 'd=e']), + (r'a="b\"f" c\FF d=\"e', ['a=b"f', '\xff', 'c', 'd="e']), +] + + +@pytest.mark.parametrize("command, result", TEST_SPLIT_ROUTEROS) +def test_split_routeros(command, result): + result_ = api.split_routeros(command) + print(result_, result) + assert result_ == result + + +TEST_SPLIT_ROUTEROS_ERRORS = [ + (r'a="b\"f" c\FF d="e', 'Unexpected end of string during escaped parameter'), +] + + +@pytest.mark.parametrize("command, message", TEST_SPLIT_ROUTEROS_ERRORS) +def test_split_routeros_errors(command, message): + with pytest.raises(api.ParseError) as exc: + api.split_routeros(command) + print(exc.value.args[0], message) + assert exc.value.args[0] == message From f9d246cd7a9ca9e8724723fb70acb968aa2149d5 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 9 Oct 2021 13:36:14 +0200 Subject: [PATCH 006/365] Make command always return changed=true. (#50) --- changelogs/fragments/50-command-changed.yml | 2 ++ plugins/modules/command.py | 5 ++++- tests/unit/plugins/modules/test_command.py | 12 ++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/50-command-changed.yml diff --git a/changelogs/fragments/50-command-changed.yml b/changelogs/fragments/50-command-changed.yml new file mode 100644 index 0000000..fec925a --- /dev/null +++ b/changelogs/fragments/50-command-changed.yml @@ -0,0 +1,2 @@ +breaking_changes: +- "command - the module now always indicates that a change happens. If this is not correct, please use ``changed_when`` to determine the correct changed status for a task (https://github.com/ansible-collections/community.routeros/pull/50)." diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 82331a5..a96c7f0 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -15,6 +15,9 @@ description: read from the device. This module includes an argument that will cause the module to wait for a specific condition before returning or timing out if the condition is not met. + - The module always indicates a (changed) status. You can use + R(the changed_when task property,override_the_changed_result) to determine + whether a command task actually resulted in a change or not. options: commands: description: @@ -168,7 +171,7 @@ def main(): module.fail_json(msg=msg, failed_conditions=failed_conditions) result.update({ - 'changed': False, + 'changed': True, 'stdout': responses, 'stdout_lines': list(to_lines(responses)) }) diff --git a/tests/unit/plugins/modules/test_command.py b/tests/unit/plugins/modules/test_command.py index ab045fe..0bb4f07 100644 --- a/tests/unit/plugins/modules/test_command.py +++ b/tests/unit/plugins/modules/test_command.py @@ -61,20 +61,20 @@ class TestRouterosCommandModule(TestRouterosModule): def test_command_simple(self): set_module_args(dict(commands=['/system resource print'])) - result = self.execute_module() + result = self.execute_module(changed=True) self.assertEqual(len(result['stdout']), 1) self.assertTrue('platform: "MikroTik"' in result['stdout'][0]) def test_command_multiple(self): set_module_args(dict(commands=['/system resource print', '/system resource print'])) - result = self.execute_module() + result = self.execute_module(changed=True) self.assertEqual(len(result['stdout']), 2) self.assertTrue('platform: "MikroTik"' in result['stdout'][0]) def test_command_wait_for(self): wait_for = 'result[0] contains "MikroTik"' set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)) - self.execute_module() + self.execute_module(changed=True) def test_command_wait_for_fails(self): wait_for = 'result[0] contains "test string"' @@ -92,13 +92,13 @@ class TestRouterosCommandModule(TestRouterosModule): wait_for = ['result[0] contains "MikroTik"', 'result[0] contains "test string"'] set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='any')) - self.execute_module() + self.execute_module(changed=True) def test_command_match_all(self): wait_for = ['result[0] contains "MikroTik"', 'result[0] contains "RB1100"'] set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='all')) - self.execute_module() + self.execute_module(changed=True) def test_command_match_all_failure(self): wait_for = ['result[0] contains "MikroTik"', @@ -110,4 +110,4 @@ class TestRouterosCommandModule(TestRouterosModule): def test_command_wait_for_2(self): wait_for = 'result[0] contains "wireless"' set_module_args(dict(commands=['/system package print'], wait_for=wait_for)) - self.execute_module() + self.execute_module(changed=True) From d73eb1c14492f49ea2448214b99f655a9f10af3c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 11 Oct 2021 23:44:40 +0200 Subject: [PATCH 007/365] Add module_utils and filters for quoting and unquoting (#53) * Move splitting code to own file. * Move list to dictionary code to quoting as well. * Add quoting functionality. * Add quoting filters. * Add integration tests to CI. * Fix bugs, increase coverage. * Make parsing more strict. * Extract function parse_argument_value from split_routeros_command to make proper parsing of WHERE possible. * Adjust expected error message in integration tests. * Simplify code and improve coverage. * Add changelog fragment for WHERE strictness in api module. * Add documenation. * Fix typo. * Add documentation references. * Add example to api module which uses quote_argument_value. * Fix bug, and add tests which prevent this in the future. * Add more escape sequence tests. * Make sure all control characters are quoted. --- .github/workflows/ansible-test.yml | 73 +++++ changelogs/fragments/53-api-where.yml | 2 + changelogs/fragments/53-quoting-filters.yml | 12 + docs/docsite/extra-docs.yml | 1 + docs/docsite/rst/quoting.rst | 14 + plugins/filter/quoting.py | 113 ++++++++ plugins/module_utils/quoting.py | 206 +++++++++++++ plugins/modules/api.py | 156 +++------- plugins/modules/command.py | 5 + plugins/modules/facts.py | 3 + .../targets/filter_quoting/aliases | 2 + .../targets/filter_quoting/tasks/main.yml | 59 ++++ .../unit/plugins/module_utils/test_quoting.py | 272 ++++++++++++++++++ tests/unit/plugins/modules/test_api.py | 30 -- 14 files changed, 803 insertions(+), 145 deletions(-) create mode 100644 changelogs/fragments/53-api-where.yml create mode 100644 changelogs/fragments/53-quoting-filters.yml create mode 100644 docs/docsite/rst/quoting.rst create mode 100644 plugins/filter/quoting.py create mode 100644 plugins/module_utils/quoting.py create mode 100644 tests/integration/targets/filter_quoting/aliases create mode 100644 tests/integration/targets/filter_quoting/tasks/main.yml create mode 100644 tests/unit/plugins/module_utils/test_quoting.py diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 9a00a3b..5777dcd 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -112,3 +112,76 @@ jobs: - uses: codecov/codecov-action@v1 with: fail_ci_if_error: false + +### +# Integration tests (RECOMMENDED) +# +# https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html + + integration: + runs-on: ubuntu-latest + name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) + strategy: + fail-fast: false + matrix: + ansible: + - stable-2.12 + - devel + python: + - 3.8 + - 3.9 + - "3.10" + include: + # 2.9 + - ansible: stable-2.9 + python: 2.7 + - ansible: stable-2.9 + python: 3.5 + - ansible: stable-2.9 + python: 3.6 + # 2.10 + - ansible: stable-2.10 + python: 3.5 + # 2.11 + - ansible: stable-2.11 + python: 2.7 + - ansible: stable-2.11 + python: 3.6 + - ansible: stable-2.11 + python: 3.9 + + steps: + - name: Check out code + uses: actions/checkout@v2 + with: + path: ansible_collections/community/routeros + + - name: Set up Python + uses: actions/setup-python@v2 + with: + # it is just required to run that once as "ansible-test integration" in the docker image + # will run on all python versions it supports. + python-version: 3.8 + + - name: Install ansible-core (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Install collection dependencies + run: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon + # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) + # 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/community.routeros + - uses: codecov/codecov-action@v1 + with: + fail_ci_if_error: false diff --git a/changelogs/fragments/53-api-where.yml b/changelogs/fragments/53-api-where.yml new file mode 100644 index 0000000..a2b09e2 --- /dev/null +++ b/changelogs/fragments/53-api-where.yml @@ -0,0 +1,2 @@ +minor_changes: +- "api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53)." diff --git a/changelogs/fragments/53-quoting-filters.yml b/changelogs/fragments/53-quoting-filters.yml new file mode 100644 index 0000000..3cbb5cd --- /dev/null +++ b/changelogs/fragments/53-quoting-filters.yml @@ -0,0 +1,12 @@ +--- +add plugin.filter: + - name: split + description: Split a command into arguments + - name: quote_argument_value + description: Quote an argument value + - name: quote_argument + description: Quote an argument + - name: join + description: Join a list of arguments to a command + - name: list_to_dict + description: Convert a list of arguments to a list of dictionary diff --git a/docs/docsite/extra-docs.yml b/docs/docsite/extra-docs.yml index cb2ef6a..385bd7e 100644 --- a/docs/docsite/extra-docs.yml +++ b/docs/docsite/extra-docs.yml @@ -4,3 +4,4 @@ sections: toctree: - api-guide - ssh-guide + - quoting diff --git a/docs/docsite/rst/quoting.rst b/docs/docsite/rst/quoting.rst new file mode 100644 index 0000000..f17a861 --- /dev/null +++ b/docs/docsite/rst/quoting.rst @@ -0,0 +1,14 @@ +.. _ansible_collections.community.routeros.docsite.quoting: + +How to quote and unquote commands and arguments +=============================================== + +When using the :ref:`community.routeros.command module ` or the :ref:`community.routeros.api module ` modules, you need to pass text data in quoted form. While in some cases quoting is not needed (when passing IP addresses or names without spaces, for example), in other cases it is required, like when passing a comment which contains a space. + +The community.routeros collection provides a set of Jinja2 filter plugins which helps you with these tasks: + +- The ``community.routeros.quote_argument_value`` filter quotes an argument value: ``'this is a "comment"' | community.routeros.quote_argument_value == '"this is a \\"comment\\""'``. +- The ``community.routeros.quote_argument`` filter quotes an argument with or without a value: ``'comment=this is a "comment"' | community.routeros.quote_argument == 'comment="this is a \\"comment\\""'``. +- The ``community.routeros.join`` filter quotes a list of arguments and joins them to one string: ``['foo=bar', 'comment=foo is bar'] | community.routeros.join == 'foo=bar comment="foo is bar"'``. +- The ``community.routeros.split`` filter splits a command into a list of arguments (with or without values): ``'foo=bar comment="foo is bar"' | community.routeros.split == ['foo=bar', 'comment=foo is bar']`` +- The ``community.routeros.list_to_dict`` filter splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: ``require_assignment`` (default value ``true``) allows to accept arguments without values when set to ``false``; and ``skip_empty_values`` (default value ``false``) allows to skip arguments whose value is empty. diff --git a/plugins/filter/quoting.py b/plugins/filter/quoting.py new file mode 100644 index 0000000..aabb421 --- /dev/null +++ b/plugins/filter/quoting.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Felix Fontein +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.errors import AnsibleFilterError +from ansible.module_utils.common.text.converters import to_text + +from ansible_collections.community.routeros.plugins.module_utils.quoting import ( + ParseError, + convert_list_to_dictionary, + join_routeros_command, + quote_routeros_argument, + quote_routeros_argument_value, + split_routeros_command, +) + + +def wrap_exception(fn, *args, **kwargs): + try: + return fn(*args, **kwargs) + except ParseError as e: + raise AnsibleFilterError(to_text(e)) + + +def split(line): + ''' + Split a command into arguments. + + Example: + 'add name=wrap comment="with space"' + is converted to: + ['add', 'name=wrap', 'comment=with space'] + ''' + return wrap_exception(split_routeros_command, line) + + +def quote_argument_value(argument): + ''' + Quote an argument value. + + Example: + 'with "space"' + is converted to: + r'"with \"space\""' + ''' + return wrap_exception(quote_routeros_argument_value, argument) + + +def quote_argument(argument): + ''' + Quote an argument. + + Example: + 'comment=with "space"' + is converted to: + r'comment="with \"space\""' + ''' + return wrap_exception(quote_routeros_argument, argument) + + +def join(arguments): + ''' + Join a list of arguments to a command. + + Example: + ['add', 'name=wrap', 'comment=with space'] + is converted to: + 'add name=wrap comment="with space"' + ''' + return wrap_exception(join_routeros_command, arguments) + + +def list_to_dict(string_list, require_assignment=True, skip_empty_values=False): + ''' + Convert a list of arguments to a list of dictionary. + + Example: + ['foo=bar', 'comment=with space', 'additional='] + is converted to: + {'foo': 'bar', 'comment': 'with space', 'additional': ''} + + If require_assignment is True (default), arguments without assignments are + rejected. (Example: in ['add', 'name=foo'], 'add' is an argument without + assignment.) If it is False, these are given value None. + + If skip_empty_values is True, arguments with empty value are removed from + the result. (Example: in ['name='], 'name' has an empty value.) + If it is False (default), these are kept. + + ''' + return wrap_exception( + convert_list_to_dictionary, + string_list, + require_assignment=require_assignment, + skip_empty_values=skip_empty_values, + ) + + +class FilterModule(object): + '''Ansible jinja2 filters for RouterOS command quoting and unquoting''' + + def filters(self): + return { + 'split': split, + 'quote_argument': quote_argument, + 'quote_argument_value': quote_argument_value, + 'join': join, + 'list_to_dict': list_to_dict, + } diff --git a/plugins/module_utils/quoting.py b/plugins/module_utils/quoting.py new file mode 100644 index 0000000..61d67da --- /dev/null +++ b/plugins/module_utils/quoting.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +import sys + +from ansible.module_utils.common.text.converters import to_native, to_bytes + + +class ParseError(Exception): + pass + + +ESCAPE_SEQUENCES = { + b'"': b'"', + b'\\': b'\\', + b'?': b'?', + b'$': b'$', + b'_': b'_', + b'a': b'\a', + b'b': b'\b', + b'f': b'\xFF', + b'n': b'\n', + b'r': b'\r', + b't': b'\t', + b'v': b'\v', +} + +ESCAPE_SEQUENCE_REVERSED = dict([(v, k) for k, v in ESCAPE_SEQUENCES.items()]) + +ESCAPE_DIGITS = b'0123456789ABCDEF' + + +if sys.version_info[0] < 3: + _int_to_byte = chr +else: + def _int_to_byte(value): + return bytes((value, )) + + +def parse_argument_value(line, start_index=0, must_match_everything=True): + ''' + Parse an argument value (quoted or not quoted) from ``line``. + + Will start at offset ``start_index``. Returns pair ``(parsed_value, + end_index)``, where ``end_index`` is the first character after the + attribute. + + If ``must_match_everything`` is ``True`` (default), will fail if + ``end_index < len(line)``. + ''' + line = to_bytes(line) + length = len(line) + index = start_index + if index == length: + raise ParseError('Expected value, but found end of string') + quoted = False + if line[index:index + 1] == b'"': + quoted = True + index += 1 + current = [] + while index < length: + ch = line[index:index + 1] + index += 1 + if not quoted and ch == b' ': + index -= 1 + break + elif ch == b'"': + if quoted: + quoted = False + if line[index:index + 1] not in (b'', b' '): + raise ParseError('Ending \'"\' must be followed by space or end of string') + break + raise ParseError('\'"\' must not appear in an unquoted value') + elif ch == b'\\': + if not quoted: + raise ParseError('Escape sequences can only be used inside double quotes') + if index == length: + raise ParseError('\'\\\' must not be at the end of the line') + ch = line[index:index + 1] + index += 1 + if ch in ESCAPE_SEQUENCES: + current.append(ESCAPE_SEQUENCES[ch]) + else: + d1 = ESCAPE_DIGITS.find(ch) + if d1 < 0: + raise ParseError('Invalid escape sequence \'\\{0}\''.format(to_native(ch))) + if index == length: + raise ParseError('Hex escape sequence cut off at end of line') + ch2 = line[index:index + 1] + d2 = ESCAPE_DIGITS.find(ch2) + index += 1 + if d2 < 0: + raise ParseError('Invalid hex escape sequence \'\\{0}\''.format(to_native(ch + ch2))) + current.append(_int_to_byte(d1 * 16 + d2)) + else: + if not quoted and ch in (b"'", b'=', b'(', b')', b'$', b'[', b'{', b'`'): + raise ParseError('"{0}" can only be used inside double quotes'.format(to_native(ch))) + if ch == b'?': + raise ParseError('"{0}" can only be used in escaped form'.format(to_native(ch))) + current.append(ch) + if quoted: + raise ParseError('Unexpected end of string during escaped parameter') + if must_match_everything and index < length: + raise ParseError('Unexpected data at end of value') + return to_native(b''.join(current)), index + + +def split_routeros_command(line): + line = to_bytes(line) + result = [] + current = [] + index = 0 + length = len(line) + parsing_attribute_name = False + while index < length: + ch = line[index:index + 1] + index += 1 + if ch == b' ': + if parsing_attribute_name: + parsing_attribute_name = False + result.append(b''.join(current)) + current = [] + elif ch == b'=' and parsing_attribute_name: + current.append(ch) + value, index = parse_argument_value(line, start_index=index, must_match_everything=False) + current.append(to_bytes(value)) + parsing_attribute_name = False + result.append(b''.join(current)) + current = [] + elif ch in (b'"', b'\\', b"'", b'=', b'(', b')', b'$', b'[', b'{', b'`', b'?'): + raise ParseError('Found unexpected "{0}"'.format(to_native(ch))) + else: + current.append(ch) + parsing_attribute_name = True + if parsing_attribute_name and current: + result.append(b''.join(current)) + return [to_native(part) for part in result] + + +def quote_routeros_argument_value(argument): + argument = to_bytes(argument) + result = [] + quote = False + length = len(argument) + index = 0 + while index < length: + letter = argument[index:index + 1] + index += 1 + if letter in ESCAPE_SEQUENCE_REVERSED: + result.append(b'\\%s' % ESCAPE_SEQUENCE_REVERSED[letter]) + quote = True + continue + elif ord(letter) < 32: + v = ord(letter) + v1 = v % 16 + v2 = v // 16 + result.append(b'\\%s%s' % (ESCAPE_DIGITS[v2:v2 + 1], ESCAPE_DIGITS[v1:v1 + 1])) + quote = True + continue + elif letter in (b' ', b'=', b';', b"'"): + quote = True + result.append(letter) + argument = to_native(b''.join(result)) + if quote or not argument: + argument = '"%s"' % argument + return argument + + +def quote_routeros_argument(argument): + def check_attribute(attribute): + if ' ' in attribute: + raise ParseError('Attribute names must not contain spaces') + return attribute + + if '=' not in argument: + check_attribute(argument) + return argument + + attribute, value = argument.split('=', 1) + check_attribute(attribute) + value = quote_routeros_argument_value(value) + return '%s=%s' % (attribute, value) + + +def join_routeros_command(arguments): + return ' '.join([quote_routeros_argument(argument) for argument in arguments]) + + +def convert_list_to_dictionary(string_list, require_assignment=True, skip_empty_values=False): + dictionary = {} + for p in string_list: + if '=' not in p: + if require_assignment: + raise ParseError("missing '=' after '%s'" % p) + dictionary[p] = None + continue + p = p.split('=', 1) + if not skip_empty_values or p[1]: + dictionary[p[0]] = p[1] + return dictionary diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 93ea250..2fe904c 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -119,6 +119,11 @@ options: - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). type: path version_added: 1.2.0 +seealso: + - ref: ansible_collections.community.routeros.docsite.api-guide + description: How to connect to RouterOS devices with the RouterOS API + - ref: ansible_collections.community.routeros.docsite.quoting + description: How to quote and unquote commands and arguments ''' EXAMPLES = ''' @@ -190,7 +195,10 @@ EXAMPLES = ''' password: "{{ password }}" username: "{{ username }}" path: "{{ path }}" - update: ".id={{ query_id }} address={{ ip3 }}" + update: >- + .id={{ query_id }} + address={{ ip3 }} + comment={{ 'A comment with spaces' | community.routeros.quote_argument_value }} register: updateout - name: Dump "Update" output @@ -258,8 +266,16 @@ message: from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import missing_required_lib -from ansible.module_utils.common.text.converters import to_native, to_bytes +from ansible.module_utils.common.text.converters import to_native +from ansible_collections.community.routeros.plugins.module_utils.quoting import ( + ParseError, + convert_list_to_dictionary, + parse_argument_value, + split_routeros_command, +) + +import re import ssl import traceback @@ -274,95 +290,6 @@ except Exception as e: LIB_IMP_ERR = traceback.format_exc() -class ParseError(Exception): - pass - - -ESCAPE_SEQUENCES = { - b'"': b'"', - b'\\': b'\\', - b'?': b'?', - b'$': b'$', - b'_': b'_', - b'a': b'\a', - b'b': b'\b', - b'f': b'\xFF', - b'n': b'\n', - b'r': b'\r', - b't': b'\t', - b'v': b'\v', -} - -ESCAPE_DIGITS = b'0123456789ABCDEF' - - -def split_routeros(line): - line = to_bytes(line) - result = [] - current = [] - index = 0 - length = len(line) - # States: - # 0 = outside param - # 1 = param before '=' - # 2 = param after '=' without quote - # 3 = param after '=' with quote - state = 0 - while index < length: - ch = line[index:index + 1] - index += 1 - if state == 0 and ch == b' ': - pass - elif state in (1, 2) and ch == b' ': - state = 0 - result.append(b''.join(current)) - current = [] - elif ch == b'=' and state == 1: - state = 2 - current.append(ch) - if index + 1 < length and line[index:index + 1] == b'"': - state = 3 - index += 1 - elif ch == b'"': - if state == 3: - state = 0 - result.append(b''.join(current)) - current = [] - if index + 1 < length and line[index:index + 1] != b' ': - raise ParseError('Ending \'"\' must be followed by space or end of string') - else: - raise ParseError('\'"\' must follow \'=\'') - elif ch == b'\\': - if index + 1 == length: - raise ParseError('\'\\\' must not be at the end of the line') - ch = line[index:index + 1] - index += 1 - if ch in ESCAPE_SEQUENCES: - current.append(ch) - else: - d1 = ESCAPE_DIGITS.find(ch) - if d1 < 0: - raise ParseError('Invalid escape sequence \'\\{0}\''.format(ch)) - if index + 1 == length: - raise ParseError('Hex escape sequence cut off at end of line') - ch2 = line[index:index + 1] - d2 = ESCAPE_DIGITS.find(ch2) - index += 1 - if d2 < 0: - raise ParseError('Invalid hex escape sequence \'\\{0}{1}\''.format(ch, ch2)) - result.append(chr(d1 * 16 + d2)) - else: - current.append(ch) - if state == 0: - state = 1 - if state in (1, 2): - if current: - result.append(b''.join(current)) - elif state == 3: - raise ParseError('Unexpected end of string during escaped parameter') - return [to_native(part) for part in result] - - class ROS_api_module: def __init__(self): module_args = dict( @@ -410,7 +337,24 @@ class ROS_api_module: self.where = None self.query = self.module.params['query'] if self.query: - self.query = self.list_remove_empty(self.split_params(self.query)) + where_index = self.query.find(' WHERE ') + if where_index < 0: + self.query = self.split_params(self.query) + else: + where = self.query[where_index + len(' WHERE '):] + self.query = self.split_params(self.query[:where_index]) + # where must be of the format ' ' + m = re.match(r'^\s*([^ ]+)\s+([^ ]+)\s+(.*)$', where) + if not m: + self.errors("invalid syntax for 'WHERE %s'" % where) + try: + self.where = [ + m.group(1), # attribute + m.group(2), # operator + parse_argument_value(m.group(3).rstrip())[0], # value + ] + except ParseError as exc: + self.errors("invalid syntax for 'WHERE %s': %s" % (where, exc)) try: idx = self.query.index('WHERE') self.where = self.query[idx + 1:] @@ -439,26 +383,14 @@ class ROS_api_module: else: self.api_get_all() - def list_remove_empty(self, check_list): - while("" in check_list): - check_list.remove("") - return check_list - def list_to_dic(self, ldict): - dict = {} - for p in ldict: - if '=' not in p: - self.errors("missing '=' after '%s'" % p) - p = p.split('=', 1) - if p[1]: - dict[p[0]] = p[1] - return dict + return convert_list_to_dictionary(ldict, skip_empty_values=True, require_assignment=True) def split_params(self, params): if not isinstance(params, str): raise AssertionError('Parameters can only be a string, received %s' % type(params)) try: - return split_routeros(params) + return split_routeros_command(params) except ParseError as e: self.module.fail_json(msg=to_native(e)) @@ -512,11 +444,6 @@ class ROS_api_module: keys[k] = Key(k) try: if self.where: - if len(self.where) < 3: - self.errors("invalid syntax for 'WHERE %s'" - % ' '.join(self.where)) - - where = [] if self.where[1] == '==': select = self.api_path.select(*keys).where(keys[self.where[0]] == self.where[2]) elif self.where[1] == '!=': @@ -528,11 +455,10 @@ class ROS_api_module: else: self.errors("'%s' is not operator for 'where'" % self.where[1]) - for row in select: - self.result['message'].append(row) else: - for row in self.api_path.select(*keys): - self.result['message'].append(row) + select = self.api_path.select(*keys) + for row in select: + self.result['message'].append(row) if len(self.result['message']) < 1: msg = "no results for '%s 'query' %s" % (' '.join(self.path), ' '.join(self.query)) diff --git a/plugins/modules/command.py b/plugins/modules/command.py index a96c7f0..6b0c499 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -58,6 +58,11 @@ options: conditions, the interval indicates how long to wait before trying the command again. default: 1 +seealso: + - ref: ansible_collections.community.routeros.docsite.ssh-guide + description: How to connect to RouterOS devices with SSH + - ref: ansible_collections.community.routeros.docsite.quoting + description: How to quote and unquote commands and arguments ''' EXAMPLES = """ diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 6b37f23..2de3c21 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -27,6 +27,9 @@ options: not be collected. required: false default: '!config' +seealso: + - ref: ansible_collections.community.routeros.docsite.ssh-guide + description: How to connect to RouterOS devices with SSH ''' EXAMPLES = """ diff --git a/tests/integration/targets/filter_quoting/aliases b/tests/integration/targets/filter_quoting/aliases new file mode 100644 index 0000000..54ea5a3 --- /dev/null +++ b/tests/integration/targets/filter_quoting/aliases @@ -0,0 +1,2 @@ +shippable/posix/group1 +skip/python2.6 diff --git a/tests/integration/targets/filter_quoting/tasks/main.yml b/tests/integration/targets/filter_quoting/tasks/main.yml new file mode 100644 index 0000000..a871cfc --- /dev/null +++ b/tests/integration/targets/filter_quoting/tasks/main.yml @@ -0,0 +1,59 @@ +--- +- name: "Test split filter" + assert: + that: + - "'' | community.routeros.split == []" + - "'foo bar' | community.routeros.split == ['foo', 'bar']" + - > + 'foo bar="a b c"' | community.routeros.split == ['foo', 'bar=a b c'] + +- name: "Test split filter error handling" + set_fact: + test: >- + {{ 'a="' | community.routeros.split }} + ignore_errors: true + register: result + +- name: "Verify split filter error handling" + assert: + that: + - >- + result.msg == "Unexpected end of string during escaped parameter" + +- name: "Test quote_argument filter" + assert: + that: + - > + 'a=' | community.routeros.quote_argument == 'a=""' + - > + 'a=b' | community.routeros.quote_argument == 'a=b' + - > + 'a=b c' | community.routeros.quote_argument == 'a="b c"' + - > + 'a=""' | community.routeros.quote_argument == 'a="\\"\\""' + +- name: "Test quote_argument_value filter" + assert: + that: + - > + '' | community.routeros.quote_argument_value == '""' + - > + 'foo' | community.routeros.quote_argument_value == 'foo' + - > + '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo bar\\""' + +- name: "Test join filter" + assert: + that: + - > + ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c d"' + +- name: "Test list_to_dict filter" + assert: + that: + - > + ['a=', 'b=c'] | community.routeros.list_to_dict == {'a': '', 'b': 'c'} + - > + ['a=', 'b=c'] | community.routeros.list_to_dict(skip_empty_values=True) == {'b': 'c'} + - > + ['a', 'b=c'] | community.routeros.list_to_dict(require_assignment=False) == {'a': none, 'b': 'c'} diff --git a/tests/unit/plugins/module_utils/test_quoting.py b/tests/unit/plugins/module_utils/test_quoting.py new file mode 100644 index 0000000..15d6142 --- /dev/null +++ b/tests/unit/plugins/module_utils/test_quoting.py @@ -0,0 +1,272 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import pytest + +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils.quoting import ( + ParseError, + convert_list_to_dictionary, + join_routeros_command, + parse_argument_value, + quote_routeros_argument, + quote_routeros_argument_value, + split_routeros_command, +) + + +TEST_PARSE_ARGUMENT_VALUE = [ + ('a', {}, ('a', 1)), + ('a ', {'must_match_everything': False}, ('a', 1)), + (r'"a b"', {}, ('a b', 5)), + (r'"b\"f"', {}, ('b"f', 6)), + (r'"\01"', {}, ('\x01', 5)), + (r'"\1F"', {}, ('\x1f', 5)), + (r'"\FF"', {}, (to_native(b'\xff'), 5)), + (r'"\"e"', {}, ('"e', 5)), + (r'"\""', {}, ('"', 4)), + (r'"\\"', {}, ('\\', 4)), + (r'"\?"', {}, ('?', 4)), + (r'"\$"', {}, ('$', 4)), + (r'"\_"', {}, ('_', 4)), + (r'"\a"', {}, ('\a', 4)), + (r'"\b"', {}, ('\b', 4)), + (r'"\f"', {}, (to_native(b'\xff'), 4)), + (r'"\n"', {}, ('\n', 4)), + (r'"\r"', {}, ('\r', 4)), + (r'"\t"', {}, ('\t', 4)), + (r'"\v"', {}, ('\v', 4)), + (r'"b=c"', {}, ('b=c', 5)), + (r'""', {}, ('', 2)), + (r'"" ', {'must_match_everything': False}, ('', 2)), + ("'e", {'start_index': 1}, ('e', 2)), +] + + +@pytest.mark.parametrize("command, kwargs, result", TEST_PARSE_ARGUMENT_VALUE) +def test_parse_argument_value(command, kwargs, result): + result_ = parse_argument_value(command, **kwargs) + print(result_, result) + assert result_ == result + + +TEST_PARSE_ARGUMENT_VALUE_ERRORS = [ + (r'"e', {}, 'Unexpected end of string during escaped parameter'), + ("'e", {}, '"\'" can only be used inside double quotes'), + (r'\FF', {}, 'Escape sequences can only be used inside double quotes'), + (r'\"e', {}, 'Escape sequences can only be used inside double quotes'), + ('e=f', {}, '"=" can only be used inside double quotes'), + ('e$', {}, '"$" can only be used inside double quotes'), + ('e(', {}, '"(" can only be used inside double quotes'), + ('e)', {}, '")" can only be used inside double quotes'), + ('e[', {}, '"[" can only be used inside double quotes'), + ('e{', {}, '"{" can only be used inside double quotes'), + ('e`', {}, '"`" can only be used inside double quotes'), + ('?', {}, '"?" can only be used in escaped form'), + (r'b"', {}, '\'"\' must not appear in an unquoted value'), + (r'""a', {}, "Ending '\"' must be followed by space or end of string"), + (r'"" ', {}, "Unexpected data at end of value"), + ('"\\', {}, r"'\' must not be at the end of the line"), + (r'"\A', {}, r'Hex escape sequence cut off at end of line'), + (r'"\Z"', {}, r"Invalid escape sequence '\Z'"), + (r'"\Aa"', {}, r"Invalid hex escape sequence '\Aa'"), +] + + +@pytest.mark.parametrize("command, kwargs, message", TEST_PARSE_ARGUMENT_VALUE_ERRORS) +def test_parse_argument_value_errors(command, kwargs, message): + with pytest.raises(ParseError) as exc: + parse_argument_value(command, **kwargs) + print(exc.value.args[0], message) + assert exc.value.args[0] == message + + +TEST_SPLIT_ROUTEROS_COMMAND = [ + ('', []), + (' ', []), + (r'a b c', ['a', 'b', 'c']), + (r'a=b c d=e', ['a=b', 'c', 'd=e']), + (r'a="b f" c d=e', ['a=b f', 'c', 'd=e']), + (r'a="b\"f" c="\FF" d="\"e"', ['a=b"f', to_native(b'c=\xff'), 'd="e']), + (r'a="b=c"', ['a=b=c']), + (r'a=b ', ['a=b']), +] + + +@pytest.mark.parametrize("command, result", TEST_SPLIT_ROUTEROS_COMMAND) +def test_split_routeros_command(command, result): + result_ = split_routeros_command(command) + print(result_, result) + assert result_ == result + + +TEST_SPLIT_ROUTEROS_COMMAND_ERRORS = [ + (r'a=', 'Expected value, but found end of string'), + (r'a="b\"f" d="e', 'Unexpected end of string during escaped parameter'), + ('d=\'e', '"\'" can only be used inside double quotes'), + (r'c\FF', r'Found unexpected "\"'), + (r'd=\"e', 'Escape sequences can only be used inside double quotes'), + ('d=e=f', '"=" can only be used inside double quotes'), + ('d=e$', '"$" can only be used inside double quotes'), + ('d=e(', '"(" can only be used inside double quotes'), + ('d=e)', '")" can only be used inside double quotes'), + ('d=e[', '"[" can only be used inside double quotes'), + ('d=e{', '"{" can only be used inside double quotes'), + ('d=e`', '"`" can only be used inside double quotes'), + ('d=?', '"?" can only be used in escaped form'), + (r'a=b"', '\'"\' must not appear in an unquoted value'), + (r'a=""a', "Ending '\"' must be followed by space or end of string"), + ('a="\\', r"'\' must not be at the end of the line"), + (r'a="\Z', r"Invalid escape sequence '\Z'"), + (r'a="\Aa', r"Invalid hex escape sequence '\Aa'"), +] + + +@pytest.mark.parametrize("command, message", TEST_SPLIT_ROUTEROS_COMMAND_ERRORS) +def test_split_routeros_command_errors(command, message): + with pytest.raises(ParseError) as exc: + split_routeros_command(command) + print(exc.value.args[0], message) + assert exc.value.args[0] == message + + +TEST_CONVERT_LIST_TO_DICTIONARY = [ + (['a=b', 'c=d=e', 'e='], {}, {'a': 'b', 'c': 'd=e', 'e': ''}), + (['a=b', 'c=d=e', 'e='], {'skip_empty_values': False}, {'a': 'b', 'c': 'd=e', 'e': ''}), + (['a=b', 'c=d=e', 'e='], {'skip_empty_values': True}, {'a': 'b', 'c': 'd=e'}), + (['a=b', 'c=d=e', 'e=', 'f'], {'require_assignment': False}, {'a': 'b', 'c': 'd=e', 'e': '', 'f': None}), +] + + +@pytest.mark.parametrize("list, kwargs, expected_dict", TEST_CONVERT_LIST_TO_DICTIONARY) +def test_convert_list_to_dictionary(list, kwargs, expected_dict): + result = convert_list_to_dictionary(list, **kwargs) + print(result, expected_dict) + assert result == expected_dict + + +TEST_CONVERT_LIST_TO_DICTIONARY_ERRORS = [ + (['a=b', 'c=d=e', 'e=', 'f'], {}, "missing '=' after 'f'"), +] + + +@pytest.mark.parametrize("list, kwargs, message", TEST_CONVERT_LIST_TO_DICTIONARY_ERRORS) +def test_convert_list_to_dictionary_errors(list, kwargs, message): + with pytest.raises(ParseError) as exc: + result = convert_list_to_dictionary(list, **kwargs) + print(exc.value.args[0], message) + assert exc.value.args[0] == message + + +TEST_JOIN_ROUTEROS_COMMAND = [ + (['a=b', 'c=d=e', 'e=', 'f', 'g=h i j', 'h="h"'], r'a=b c="d=e" e="" f g="h i j" h="\"h\""'), +] + + +@pytest.mark.parametrize("list, expected", TEST_JOIN_ROUTEROS_COMMAND) +def test_join_routeros_command(list, expected): + result = join_routeros_command(list) + print(result, expected) + assert result == expected + + +TEST_QUOTE_ROUTEROS_ARGUMENT = [ + (r'', r''), + (r'a', r'a'), + (r'a=b', r'a=b'), + (r'a=b c', r'a="b c"'), + (r'a="b c"', r'a="\"b c\""'), + (r"a='b", "a=\"'b\""), + (r"a=b'", "a=\"b'\""), + (r'a=""', r'a="\"\""'), +] + + +@pytest.mark.parametrize("argument, expected", TEST_QUOTE_ROUTEROS_ARGUMENT) +def test_quote_routeros_argument(argument, expected): + result = quote_routeros_argument(argument) + print(result, expected) + assert result == expected + + +TEST_QUOTE_ROUTEROS_ARGUMENT_ERRORS = [ + ('a b', 'Attribute names must not contain spaces'), + ('a b=c', 'Attribute names must not contain spaces'), +] + + +@pytest.mark.parametrize("argument, message", TEST_QUOTE_ROUTEROS_ARGUMENT_ERRORS) +def test_quote_routeros_argument_errors(argument, message): + with pytest.raises(ParseError) as exc: + result = quote_routeros_argument(argument) + print(exc.value.args[0], message) + assert exc.value.args[0] == message + + +TEST_QUOTE_ROUTEROS_ARGUMENT_VALUE = [ + (r'', r'""'), + (r";", r'";"'), + (r" ", r'" "'), + (r"=", r'"="'), + (r'a', r'a'), + (r'a=b', r'"a=b"'), + (r'b c', r'"b c"'), + (r'"b c"', r'"\"b c\""'), + ("'b", "\"'b\""), + ("b'", "\"b'\""), + ('"', r'"\""'), + ('\\', r'"\\"'), + ('?', r'"\?"'), + ('$', r'"\$"'), + ('_', r'"\_"'), + ('\a', r'"\a"'), + ('\b', r'"\b"'), + # (to_native(b'\xff'), r'"\f"'), + ('\n', r'"\n"'), + ('\r', r'"\r"'), + ('\t', r'"\t"'), + ('\v', r'"\v"'), + ('\x01', r'"\01"'), + ('\x1f', r'"\1F"'), +] + + +@pytest.mark.parametrize("argument, expected", TEST_QUOTE_ROUTEROS_ARGUMENT_VALUE) +def test_quote_routeros_argument_value(argument, expected): + result = quote_routeros_argument_value(argument) + print(result, expected) + assert result == expected + + +TEST_ROUNDTRIP = [ + {'a': 'b', 'c': 'd'}, + {'script': ''':local host value=[/system identity get name]; +:local date value=[/system clock get date]; +:local day [ :pick $date 4 6 ]; +:local month [ :pick $date 0 3 ]; +:local year [ :pick $date 7 11 ]; +:local name value=($host."-".$day."-".$month."-".$year); +/system backup save name=$name; +/export file=$name; +/tool fetch address="192.168.1.1" user=ros password="PASSWORD" mode=ftp dst-path=("/mikrotik/rsc/".$name.".rsc") src-path=($name.".rsc") upload=yes; +/tool fetch address="192.168.1.1" user=ros password="PASSWORD" mode=ftp dst-path=("/mikrotik/backup/".$name.".backup") src-path=($name.".backup") upload=yes; +'''}, +] + + +@pytest.mark.parametrize("dictionary", TEST_ROUNDTRIP) +def test_roundtrip(dictionary): + argument_list = ['%s=%s' % (k, v) for k, v in dictionary.items()] + command = join_routeros_command(argument_list) + resplit_list = split_routeros_command(command) + print(resplit_list, argument_list) + assert resplit_list == argument_list + re_dictionary = convert_list_to_dictionary(resplit_list) + print(re_dictionary, dictionary) + assert re_dictionary == dictionary diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index 0eabc04..cabb918 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -288,33 +288,3 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) - - -TEST_SPLIT_ROUTEROS = [ - ('', []), - (' ', []), - (r'a b c', ['a', 'b', 'c']), - (r'a=b c d=e', ['a=b', 'c', 'd=e']), - (r'a="b f" c d=e', ['a=b f', 'c', 'd=e']), - (r'a="b\"f" c\FF d=\"e', ['a=b"f', '\xff', 'c', 'd="e']), -] - - -@pytest.mark.parametrize("command, result", TEST_SPLIT_ROUTEROS) -def test_split_routeros(command, result): - result_ = api.split_routeros(command) - print(result_, result) - assert result_ == result - - -TEST_SPLIT_ROUTEROS_ERRORS = [ - (r'a="b\"f" c\FF d="e', 'Unexpected end of string during escaped parameter'), -] - - -@pytest.mark.parametrize("command, message", TEST_SPLIT_ROUTEROS_ERRORS) -def test_split_routeros_errors(command, message): - with pytest.raises(api.ParseError) as exc: - api.split_routeros(command) - print(exc.value.args[0], message) - assert exc.value.args[0] == message From f6e929ae3a98f912df4fdb3e48f253d1702f6271 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 13 Oct 2021 07:52:55 +0200 Subject: [PATCH 008/365] Prepare 2.0.0-a2 release. --- changelogs/fragments/2.0.0-a2.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.0.0-a2.yml diff --git a/changelogs/fragments/2.0.0-a2.yml b/changelogs/fragments/2.0.0-a2.yml new file mode 100644 index 0000000..99e8a41 --- /dev/null +++ b/changelogs/fragments/2.0.0-a2.yml @@ -0,0 +1 @@ +release_summary: Second prerelease for a new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. diff --git a/galaxy.yml b/galaxy.yml index f83ca29..5c9ad59 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -2,7 +2,7 @@ namespace: community name: routeros -version: 2.0.0-a1 +version: 2.0.0-a2 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From e158fcf0ae17635c2e0d38ea4d65630d7768064e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Oct 2021 08:33:45 +0200 Subject: [PATCH 009/365] Release 2.0.0-a2. --- CHANGELOG.rst | 38 ++++++++++++++++++ changelogs/changelog.yaml | 44 +++++++++++++++++++++ changelogs/fragments/2.0.0-a2.yml | 1 - changelogs/fragments/43-sanity.yml | 2 - changelogs/fragments/45-api-split.yml | 2 - changelogs/fragments/47-api-split.yml | 3 -- changelogs/fragments/50-command-changed.yml | 2 - changelogs/fragments/53-api-where.yml | 2 - changelogs/fragments/53-quoting-filters.yml | 12 ------ 9 files changed, 82 insertions(+), 24 deletions(-) delete mode 100644 changelogs/fragments/2.0.0-a2.yml delete mode 100644 changelogs/fragments/43-sanity.yml delete mode 100644 changelogs/fragments/45-api-split.yml delete mode 100644 changelogs/fragments/47-api-split.yml delete mode 100644 changelogs/fragments/50-command-changed.yml delete mode 100644 changelogs/fragments/53-api-where.yml delete mode 100644 changelogs/fragments/53-quoting-filters.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2b6ed37..3c36dd1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,44 @@ Community RouterOS Release Notes .. contents:: Topics +v2.0.0-a2 +========= + +Release Summary +--------------- + +Second prerelease for a new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. + +Minor Changes +------------- + +- api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53). + +Breaking Changes / Porting Guide +-------------------------------- + +- api - splitting commands no longer uses a naive split by whitespace, but a more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45). +- command - the module now always indicates that a change happens. If this is not correct, please use ``changed_when`` to determine the correct changed status for a task (https://github.com/ansible-collections/community.routeros/pull/50). + +Bugfixes +-------- + +- api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47). +- api - when converting result lists to dictionaries, no longer removes second ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47). +- routeros cliconf plugin - adjust function signature that was modified in Ansible after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43). + +New Plugins +----------- + +Filter +~~~~~~ + +- join - Join a list of arguments to a command +- list_to_dict - Convert a list of arguments to a list of dictionary +- quote_argument - Quote an argument +- quote_argument_value - Quote an argument value +- split - Split a command into arguments + v2.0.0-a1 ========= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 0e41513..8d3c503 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -96,3 +96,47 @@ releases: - 2.0.0-a1.yml - 39-api-fail.yml release_date: '2021-07-31' + 2.0.0-a2: + changes: + breaking_changes: + - api - splitting commands no longer uses a naive split by whitespace, but a + more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45). + - command - the module now always indicates that a change happens. If this is + not correct, please use ``changed_when`` to determine the correct changed + status for a task (https://github.com/ansible-collections/community.routeros/pull/50). + bugfixes: + - api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47). + - api - when converting result lists to dictionaries, no longer removes second + ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47). + - routeros cliconf plugin - adjust function signature that was modified in Ansible + after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43). + minor_changes: + - api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53). + release_summary: Second prerelease for a new major release with breaking changes + in the behavior of ``community.routeros.api`` and ``community.routeros.command``. + fragments: + - 2.0.0-a2.yml + - 43-sanity.yml + - 45-api-split.yml + - 47-api-split.yml + - 50-command-changed.yml + - 53-api-where.yml + - 53-quoting-filters.yml + plugins: + filter: + - description: Join a list of arguments to a command + name: join + namespace: null + - description: Convert a list of arguments to a list of dictionary + name: list_to_dict + namespace: null + - description: Quote an argument + name: quote_argument + namespace: null + - description: Quote an argument value + name: quote_argument_value + namespace: null + - description: Split a command into arguments + name: split + namespace: null + release_date: '2021-10-14' diff --git a/changelogs/fragments/2.0.0-a2.yml b/changelogs/fragments/2.0.0-a2.yml deleted file mode 100644 index 99e8a41..0000000 --- a/changelogs/fragments/2.0.0-a2.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Second prerelease for a new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. diff --git a/changelogs/fragments/43-sanity.yml b/changelogs/fragments/43-sanity.yml deleted file mode 100644 index 5c918d1..0000000 --- a/changelogs/fragments/43-sanity.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- "routeros cliconf plugin - adjust function signature that was modified in Ansible after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43)." diff --git a/changelogs/fragments/45-api-split.yml b/changelogs/fragments/45-api-split.yml deleted file mode 100644 index 2d525cb..0000000 --- a/changelogs/fragments/45-api-split.yml +++ /dev/null @@ -1,2 +0,0 @@ -breaking_changes: - - "api - splitting commands no longer uses a naive split by whitespace, but a more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45)." diff --git a/changelogs/fragments/47-api-split.yml b/changelogs/fragments/47-api-split.yml deleted file mode 100644 index 10e8033..0000000 --- a/changelogs/fragments/47-api-split.yml +++ /dev/null @@ -1,3 +0,0 @@ -bugfixes: - - "api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47)." - - "api - when converting result lists to dictionaries, no longer removes second ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47)." diff --git a/changelogs/fragments/50-command-changed.yml b/changelogs/fragments/50-command-changed.yml deleted file mode 100644 index fec925a..0000000 --- a/changelogs/fragments/50-command-changed.yml +++ /dev/null @@ -1,2 +0,0 @@ -breaking_changes: -- "command - the module now always indicates that a change happens. If this is not correct, please use ``changed_when`` to determine the correct changed status for a task (https://github.com/ansible-collections/community.routeros/pull/50)." diff --git a/changelogs/fragments/53-api-where.yml b/changelogs/fragments/53-api-where.yml deleted file mode 100644 index a2b09e2..0000000 --- a/changelogs/fragments/53-api-where.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- "api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53)." diff --git a/changelogs/fragments/53-quoting-filters.yml b/changelogs/fragments/53-quoting-filters.yml deleted file mode 100644 index 3cbb5cd..0000000 --- a/changelogs/fragments/53-quoting-filters.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -add plugin.filter: - - name: split - description: Split a command into arguments - - name: quote_argument_value - description: Quote an argument value - - name: quote_argument - description: Quote an argument - - name: join - description: Join a list of arguments to a command - - name: list_to_dict - description: Convert a list of arguments to a list of dictionary From 65034de7697c01a13626e6adf9d74220420b7d72 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Oct 2021 15:23:00 +0200 Subject: [PATCH 010/365] Replace deprecated v1 codecov updater with v2. (#54) --- .github/workflows/ansible-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 5777dcd..e9389ea 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -109,7 +109,7 @@ jobs: 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 + - uses: codecov/codecov-action@v2 with: fail_ci_if_error: false @@ -182,6 +182,6 @@ jobs: working-directory: ./ansible_collections/community/routeros # See the reports at https://codecov.io/gh/ansible-collections/community.routeros - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v2 with: fail_ci_if_error: false From 4ccd70cc8fdf3bae26153718759ca567fb76d84d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 19 Oct 2021 14:04:30 +0200 Subject: [PATCH 011/365] Fix sanity errors. (#55) --- changelogs/fragments/55-linting.yml | 3 +++ plugins/modules/command.py | 13 ++++++++++--- plugins/modules/facts.py | 4 +++- tests/sanity/ignore-2.10.txt | 5 ----- tests/sanity/ignore-2.11.txt | 5 ----- tests/sanity/ignore-2.12.txt | 5 ----- tests/sanity/ignore-2.13.txt | 5 ----- tests/sanity/ignore-2.9.txt | 3 --- 8 files changed, 16 insertions(+), 27 deletions(-) create mode 100644 changelogs/fragments/55-linting.yml delete mode 100644 tests/sanity/ignore-2.10.txt delete mode 100644 tests/sanity/ignore-2.11.txt delete mode 100644 tests/sanity/ignore-2.12.txt delete mode 100644 tests/sanity/ignore-2.13.txt delete mode 100644 tests/sanity/ignore-2.9.txt diff --git a/changelogs/fragments/55-linting.yml b/changelogs/fragments/55-linting.yml new file mode 100644 index 0000000..3507df5 --- /dev/null +++ b/changelogs/fragments/55-linting.yml @@ -0,0 +1,3 @@ +minor_changes: + - "command - the ``commands`` and ``wait_for`` options now convert the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55)." + - "facts - the ``gather_subset`` option now converts the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55)." diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 6b0c499..f292792 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -27,6 +27,8 @@ options: module is not returned until the condition is satisfied or the number of retries has expired. required: true + type: list + elements: str wait_for: description: - List of conditions to evaluate against the output of the @@ -34,6 +36,8 @@ options: before moving forward. If the conditional is not true within the configured number of retries, the task fails. See examples. + type: list + elements: str match: description: - The I(match) argument is used in conjunction with the @@ -44,6 +48,7 @@ options: satisfied. default: all choices: ['any', 'all'] + type: str retries: description: - Specifies the number of retries a command should by tried @@ -51,6 +56,7 @@ options: target device every retry and evaluated against the I(wait_for) conditions. default: 10 + type: int interval: description: - Configures the interval in seconds to wait between retries @@ -58,6 +64,7 @@ options: conditions, the interval indicates how long to wait before trying the command again. default: 1 + type: int seealso: - ref: ansible_collections.community.routeros.docsite.ssh-guide description: How to connect to RouterOS devices with SSH @@ -131,10 +138,10 @@ def main(): """main entry point for module execution """ argument_spec = dict( - commands=dict(type='list', required=True), + commands=dict(type='list', elements='str', required=True), - wait_for=dict(type='list'), - match=dict(default='all', choices=['all', 'any']), + wait_for=dict(type='list', elements='str'), + match=dict(type='str', default='all', choices=['all', 'any']), retries=dict(default=10, type='int'), interval=dict(default=1, type='int') diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 2de3c21..3015502 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -27,6 +27,8 @@ options: not be collected. required: false default: '!config' + type: list + elements: str seealso: - ref: ansible_collections.community.routeros.docsite.ssh-guide description: How to connect to RouterOS devices with SSH @@ -586,7 +588,7 @@ def main(): """main entry point for module execution """ argument_spec = dict( - gather_subset=dict(default=['!config'], type='list') + gather_subset=dict(default=['!config'], type='list', elements='str') ) argument_spec.update(routeros_argument_spec) diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt deleted file mode 100644 index 9d5934b..0000000 --- a/tests/sanity/ignore-2.10.txt +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 9d5934b..0000000 --- a/tests/sanity/ignore-2.11.txt +++ /dev/null @@ -1,5 +0,0 @@ -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.12.txt b/tests/sanity/ignore-2.12.txt deleted file mode 100644 index 9d5934b..0000000 --- a/tests/sanity/ignore-2.12.txt +++ /dev/null @@ -1,5 +0,0 @@ -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.13.txt b/tests/sanity/ignore-2.13.txt deleted file mode 100644 index 9d5934b..0000000 --- a/tests/sanity/ignore-2.13.txt +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index c1e40c7..0000000 --- a/tests/sanity/ignore-2.9.txt +++ /dev/null @@ -1,3 +0,0 @@ -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 From 9cb843b87211c6ebea71bc071847cf7a5c571638 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 31 Oct 2021 15:11:49 +0100 Subject: [PATCH 012/365] Prepare 2.0.0 release. --- changelogs/fragments/2.0.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.0.0.yml diff --git a/changelogs/fragments/2.0.0.yml b/changelogs/fragments/2.0.0.yml new file mode 100644 index 0000000..466910e --- /dev/null +++ b/changelogs/fragments/2.0.0.yml @@ -0,0 +1 @@ +release_summary: A new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. diff --git a/galaxy.yml b/galaxy.yml index 5c9ad59..e24ac9a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -2,7 +2,7 @@ namespace: community name: routeros -version: 2.0.0-a2 +version: 2.0.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 26b341f332685277274f8ed4082d7c2482a3fe53 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 31 Oct 2021 15:30:38 +0100 Subject: [PATCH 013/365] Release 2.0.0 --- CHANGELOG.rst | 22 ++++++---------------- changelogs/changelog.yaml | 13 +++++++++++++ changelogs/fragments/2.0.0.yml | 1 - changelogs/fragments/55-linting.yml | 3 --- 4 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 changelogs/fragments/2.0.0.yml delete mode 100644 changelogs/fragments/55-linting.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3c36dd1..347399d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,22 +5,25 @@ Community RouterOS Release Notes .. contents:: Topics -v2.0.0-a2 -========= +v2.0.0 +====== Release Summary --------------- -Second prerelease for a new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. +A new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. Minor Changes ------------- - api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53). +- command - the ``commands`` and ``wait_for`` options now convert the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55). +- facts - the ``gather_subset`` option now converts the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55). Breaking Changes / Porting Guide -------------------------------- +- api - due to a programming error, the module never failed on errors. This has now been fixed. If you are relying on the module not failing in case of idempotent commands (resulting in errors like ``failure: already have such address``), you need to adjust your roles/playbooks. We suggest to use ``failed_when`` to accept failure in specific circumstances, for example ``failed_when: "'failure: already have ' in result.msg[0]"`` (https://github.com/ansible-collections/community.routeros/pull/39). - api - splitting commands no longer uses a naive split by whitespace, but a more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45). - command - the module now always indicates that a change happens. If this is not correct, please use ``changed_when`` to determine the correct changed status for a task (https://github.com/ansible-collections/community.routeros/pull/50). @@ -43,19 +46,6 @@ Filter - quote_argument_value - Quote an argument value - split - Split a command into arguments -v2.0.0-a1 -========= - -Release Summary ---------------- - -First prerelease for a new major release with a breaking change in the behavior of ``community.routeros.api``. - -Breaking Changes / Porting Guide --------------------------------- - -- api - due to a programming error, the module never failed on errors. This has now been fixed. If you are relying on the module not failing in case of idempotent commands (resulting in errors like ``failure: already have such address``), you need to adjust your roles/playbooks. We suggest to use ``failed_when`` to accept failure in specific circumstances, for example ``failed_when: "'failure: already have ' in result.msg[0]"`` (https://github.com/ansible-collections/community.routeros/pull/39). - v1.2.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 8d3c503..4fbd1db 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -81,6 +81,19 @@ releases: - 37-api-validate-cert-options.yml - ansible-core-_text.yml release_date: '2021-06-29' + 2.0.0: + changes: + minor_changes: + - command - the ``commands`` and ``wait_for`` options now convert the list elements + to strings (https://github.com/ansible-collections/community.routeros/pull/55). + - facts - the ``gather_subset`` option now converts the list elements to strings + (https://github.com/ansible-collections/community.routeros/pull/55). + release_summary: A new major release with breaking changes in the behavior of + ``community.routeros.api`` and ``community.routeros.command``. + fragments: + - 2.0.0.yml + - 55-linting.yml + release_date: '2021-10-31' 2.0.0-a1: changes: breaking_changes: diff --git a/changelogs/fragments/2.0.0.yml b/changelogs/fragments/2.0.0.yml deleted file mode 100644 index 466910e..0000000 --- a/changelogs/fragments/2.0.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: A new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. diff --git a/changelogs/fragments/55-linting.yml b/changelogs/fragments/55-linting.yml deleted file mode 100644 index 3507df5..0000000 --- a/changelogs/fragments/55-linting.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - "command - the ``commands`` and ``wait_for`` options now convert the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55)." - - "facts - the ``gather_subset`` option now converts the list elements to strings (https://github.com/ansible-collections/community.routeros/pull/55)." From 46035077138302ca8b86aa1e532c775b7cb96d33 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 16 Nov 2021 22:00:07 +0100 Subject: [PATCH 014/365] Restrict librouteros for Ansible 2.9 unit tests. (#57) --- .github/workflows/ansible-test.yml | 7 +++++++ tests/unit/requirements-stable-2.9.txt | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 tests/unit/requirements-stable-2.9.txt diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index e9389ea..ee69509 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -85,6 +85,13 @@ jobs: with: path: ansible_collections/community/routeros + - name: Overwrite unit test requirements (if applicable) + run: | + if [ -e tests/unit/requirements-${{ matrix.ansible }}.txt ]; then + cp tests/unit/requirements-${{ matrix.ansible }}.txt tests/unit/requirements.txt + fi + working-directory: ./ansible_collections/community/routeros + - name: Set up Python ${{ matrix.ansible }} uses: actions/setup-python@v2 with: diff --git a/tests/unit/requirements-stable-2.9.txt b/tests/unit/requirements-stable-2.9.txt new file mode 100644 index 0000000..1aa8523 --- /dev/null +++ b/tests/unit/requirements-stable-2.9.txt @@ -0,0 +1,4 @@ +unittest2 ; python_version <= '2.6' + +# requirements for api module +librouteros < 3.2.0 ; python_version >= '3.6' From e74687a8e035799c4d3f3497d499020ac1485ce9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 16 Nov 2021 22:03:31 +0100 Subject: [PATCH 015/365] Add patchback config. --- .github/patchback.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/patchback.yml diff --git a/.github/patchback.yml b/.github/patchback.yml new file mode 100644 index 0000000..33ad6e8 --- /dev/null +++ b/.github/patchback.yml @@ -0,0 +1,5 @@ +--- +backport_branch_prefix: patchback/backports/ +backport_label_prefix: backport- +target_branch_prefix: stable- +... From 656c115697766128378b60d1c57601c1b40be585 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 25 Nov 2021 20:59:19 +0100 Subject: [PATCH 016/365] Also collect coverage during sanity tests. (#59) --- .github/workflows/ansible-test.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index ee69509..d2a20ca 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -57,9 +57,19 @@ jobs: # 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 + run: ansible-test sanity --docker -v --color --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@v2 + with: + fail_ci_if_error: false + ### # Unit tests (OPTIONAL) # From 1deeb9f37226d04b1bf0c7ab63d7d24c3570e4cd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 25 Nov 2021 21:21:55 +0100 Subject: [PATCH 017/365] Restrict branches for which to run tests. --- .github/workflows/ansible-test.yml | 3 +++ .github/workflows/extra-tests.yml | 3 +++ .github/workflows/import-galaxy.yml | 1 + 3 files changed, 7 insertions(+) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index d2a20ca..5451941 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -2,6 +2,9 @@ name: CI on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests push: + branches: + - main + - stable-* pull_request: # Run CI once per day (at 06:00 UTC) schedule: diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index e04bf11..35990ef 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -2,6 +2,9 @@ name: extra-tests on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests push: + branches: + - main + - stable-* pull_request: # Run CI once per day (at 06:00 UTC) # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index bb2e488..beb370b 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - stable-* pull_request: env: From e9fdf19253e7bcdc032efcd3337e73623b2880f9 Mon Sep 17 00:00:00 2001 From: txt-file <44214237+txt-file@users.noreply.github.com> Date: Sat, 22 Jan 2022 08:26:53 +0100 Subject: [PATCH 018/365] fix typo (#64) --- plugins/modules/facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 3015502..d5589c3 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -12,7 +12,7 @@ author: "Egor Zaitsev (@heuels)" short_description: Collect facts from remote devices running MikroTik RouterOS description: - Collects a base set of device facts from a remote device that - is running RotuerOS. This module prepends all of the + is running RouterOS. This module prepends all of the base network fact keys with C(ansible_net_). The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. From a46c7df15c1e487367fbf12cf27b52c8678d1b3b Mon Sep 17 00:00:00 2001 From: Nikolay Dachev Date: Thu, 10 Feb 2022 08:53:08 +0200 Subject: [PATCH 019/365] Fix query (#68) * fix issues #67 * fix query id check * add changelog fragment * fix changelog fragment new line * fix changelog fragment new line2 * Update changelogs/fragments/68-fix-query-id-check.yml Co-authored-by: Felix Fontein Co-authored-by: Felix Fontein --- changelogs/fragments/68-fix-query-id-check.yml | 2 ++ plugins/modules/api.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/68-fix-query-id-check.yml diff --git a/changelogs/fragments/68-fix-query-id-check.yml b/changelogs/fragments/68-fix-query-id-check.yml new file mode 100644 index 0000000..c5abb53 --- /dev/null +++ b/changelogs/fragments/68-fix-query-id-check.yml @@ -0,0 +1,2 @@ +bugfixes: + - "query - fix query function check for ``.id`` vs. ``id`` arguments to not conflict with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, https://github.com/ansible-collections/community.routeros/issues/67)." diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 2fe904c..e4e716c 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -79,7 +79,7 @@ options: type: str query: description: - - Query given path for selected query attributes from RouterOS aip and return '.id'. + - Query given path for selected query attributes from RouterOS aip. - WHERE is key word which extend query. WHERE format is key operator value - with spaces. - WHERE valid operators are C(==), C(!=), C(>), C(<). - Example path C(ip address) and query C(.id address) will return only C(.id) and C(address) for all items in C(ip address) path. @@ -439,7 +439,7 @@ class ROS_api_module: def api_query(self): keys = {} for k in self.query: - if 'id' in k and k != ".id": + if k == 'id': self.errors("'%s' must be '.id'" % k) keys[k] = Key(k) try: From 5105c423c84733f0912b40b603c9bfa13d59afe2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 22 Mar 2022 07:04:34 +0100 Subject: [PATCH 020/365] Add collection links file. (#71) --- docs/docsite/links.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/docsite/links.yml diff --git a/docs/docsite/links.yml b/docs/docsite/links.yml new file mode 100644 index 0000000..d95c205 --- /dev/null +++ b/docs/docsite/links.yml @@ -0,0 +1,23 @@ +--- +edit_on_github: + repository: ansible-collections/community.routeros + branch: main + path_prefix: '' + +extra_links: + - description: Submit a bug report + url: https://github.com/ansible-collections/community.routeros/issues/new?assignees=&labels=&template=bug_report.md + - description: Request a feature + url: https://github.com/ansible-collections/community.routeros/issues/new?assignees=&labels=&template=feature_request.md + +communication: + matrix_rooms: + - topic: General usage and support questions + room: '#users:ansible.im' + irc_channels: + - topic: General usage and support questions + network: Libera + channel: '#ansible' + mailing_lists: + - topic: Ansible Project List + url: https://groups.google.com/g/ansible-project From a8ba15e556b844b1238005c70724ba871854f737 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 29 Mar 2022 06:16:43 +0200 Subject: [PATCH 021/365] Add stable-2.13 to CI. (#72) --- .github/workflows/ansible-test.yml | 13 ++++++++----- README.md | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 5451941..780a743 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -28,6 +28,7 @@ jobs: - stable-2.10 - stable-2.11 - stable-2.12 + - stable-2.13 - devel runs-on: ubuntu-latest steps: @@ -90,6 +91,7 @@ jobs: - stable-2.10 - stable-2.11 - stable-2.12 + - stable-2.13 - devel steps: @@ -145,7 +147,7 @@ jobs: fail-fast: false matrix: ansible: - - stable-2.12 + - stable-2.13 - devel python: - 3.8 @@ -157,8 +159,6 @@ jobs: python: 2.7 - ansible: stable-2.9 python: 3.5 - - ansible: stable-2.9 - python: 3.6 # 2.10 - ansible: stable-2.10 python: 3.5 @@ -167,8 +167,11 @@ jobs: python: 2.7 - ansible: stable-2.11 python: 3.6 - - ansible: stable-2.11 - python: 3.9 + # 2.12 + - ansible: stable-2.12 + python: 3.8 + - ansible: stable-2.12 + python: "3.10" steps: - name: Check out code diff --git a/README.md b/README.md index 7c8417c..f501c15 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ You can find [documentation for the modules and plugins in this collection here] ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11 and ansible-core 2.12 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12 and ansible-core 2.13 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements From 3e39e8473f030168f63051e3e863dcc4a68f7588 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 30 Mar 2022 08:06:30 +0200 Subject: [PATCH 022/365] Replace antsibull-lint collection-docs with antsibull-docs lint-collection-docs. (#73) --- tests/sanity/extra/extra-docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py index f4b7f59..f3b40fb 100755 --- a/tests/sanity/extra/extra-docs.py +++ b/tests/sanity/extra/extra-docs.py @@ -14,7 +14,7 @@ def main(): """Main entry point.""" if not os.path.isdir(os.path.join('docs', 'docsite')): return - p = subprocess.run(['antsibull-lint', 'collection-docs', '.'], check=False) + p = subprocess.run(['antsibull-docs', 'lint-collection-docs', '.'], check=False) if p.returncode not in (0, 3): print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) From cf2882772f264fd22526ff908eb1df4b858a2345 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 10 Apr 2022 10:52:48 +0200 Subject: [PATCH 023/365] Switch from antsibull to antsibull-docs. (#75) --- tests/sanity/extra/extra-docs.json | 2 +- tests/sanity/extra/extra-docs.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sanity/extra/extra-docs.json b/tests/sanity/extra/extra-docs.json index a62ef37..c2e612e 100644 --- a/tests/sanity/extra/extra-docs.json +++ b/tests/sanity/extra/extra-docs.json @@ -5,6 +5,6 @@ ], "output": "path-line-column-message", "requirements": [ - "antsibull" + "antsibull-docs" ] } diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py index f3b40fb..f2746e5 100755 --- a/tests/sanity/extra/extra-docs.py +++ b/tests/sanity/extra/extra-docs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -"""Check extra collection docs with antsibull-lint.""" +"""Check extra collection docs with antsibull-docs.""" from __future__ import (absolute_import, division, print_function) __metaclass__ = type From 7b3900fd6e6f76ce278f990b102cb3e19249f63c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 11 Apr 2022 09:03:47 +0200 Subject: [PATCH 024/365] Update GHAs. (#77) --- .github/workflows/ansible-test.yml | 18 +++++++++--------- .github/workflows/extra-tests.yml | 6 +++--- .github/workflows/import-galaxy.yml | 14 +++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 780a743..984ddc7 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -37,16 +37,16 @@ jobs: # .../ansible_collections/community/routeros/ - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ansible_collections/community/routeros - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: # it is just required to run that once as "ansible-test sanity" in the docker image # will run on all python versions it supports. - python-version: 3.8 + python-version: '3.10' # Install the head of the given branch (devel, stable-2.10) - name: Install ansible-base (${{ matrix.ansible }}) @@ -96,7 +96,7 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ansible_collections/community/routeros @@ -108,9 +108,9 @@ jobs: working-directory: ./ansible_collections/community/routeros - name: Set up Python ${{ matrix.ansible }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.10' - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check @@ -175,16 +175,16 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ansible_collections/community/routeros - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: # it is just required to run that once as "ansible-test integration" in the docker image # will run on all python versions it supports. - python-version: 3.8 + python-version: '3.10' - name: Install ansible-core (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 35990ef..f68ad13 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -21,14 +21,14 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.10' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index beb370b..c7cb607 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -18,14 +18,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: ./checkout - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.10' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check @@ -52,7 +52,7 @@ jobs: run: mkdir ./artifact && mv ./checkout/${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz ./artifact - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} path: ./artifact/ @@ -64,9 +64,9 @@ jobs: - build-collection steps: - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.10' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check @@ -75,7 +75,7 @@ jobs: run: pip install galaxy-importer --disable-pip-version-check - name: Download artifact - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} From ebe6e9377397d73439a43cad3270471508eb9b51 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Apr 2022 22:38:38 +0200 Subject: [PATCH 025/365] Bump codecov action. (#79) --- .github/workflows/ansible-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 984ddc7..b93ffa2 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -70,7 +70,7 @@ jobs: working-directory: ./ansible_collections/community/routeros # See the reports at https://codecov.io/gh/ansible_collections/ansible-collections/community.routeros - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v3 with: fail_ci_if_error: false @@ -131,7 +131,7 @@ jobs: working-directory: ./ansible_collections/community/routeros # See the reports at https://codecov.io/gh/ansible_collections/ansible-collections/community.routeros - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v3 with: fail_ci_if_error: false @@ -205,6 +205,6 @@ jobs: working-directory: ./ansible_collections/community/routeros # See the reports at https://codecov.io/gh/ansible-collections/community.routeros - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v3 with: fail_ci_if_error: false From e22433b179333d3105b9d00fc8c971f3b6947c85 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 15 Apr 2022 15:07:03 +0200 Subject: [PATCH 026/365] Schedule nightly CI at 5:15. (#81) --- .github/workflows/ansible-test.yml | 4 ++-- .github/workflows/extra-tests.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index b93ffa2..6c1a30a 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -6,9 +6,9 @@ on: - main - stable-* pull_request: - # Run CI once per day (at 06:00 UTC) + # Run CI once per day (at 05:15 UTC) schedule: - - cron: '0 6 * * *' + - cron: '15 5 * * *' jobs: diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index f68ad13..5f29828 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -6,10 +6,10 @@ on: - main - stable-* pull_request: - # Run CI once per day (at 06:00 UTC) + # Run CI once per day (at 05:15 UTC) # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version schedule: - - cron: '0 6 * * *' + - cron: '15 5 * * *' env: NAMESPACE: community COLLECTION_NAME: routeros From 30afb61f86ae4c57f5569599c5c0a168056e8067 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 15 Apr 2022 19:22:39 +0200 Subject: [PATCH 027/365] Make EE ready. (#83) --- .github/workflows/ee.yml | 113 +++++++++++++++++++ changelogs/fragments/83-ee.yml | 2 + meta/ee-requirements.txt | 1 + meta/execution-environment.yml | 4 + tests/ee/all.yml | 13 +++ tests/ee/roles/filter_quoting/aliases | 2 + tests/ee/roles/filter_quoting/tasks/main.yml | 59 ++++++++++ tests/ee/roles/smoke/tasks/main.yml | 35 ++++++ 8 files changed, 229 insertions(+) create mode 100644 .github/workflows/ee.yml create mode 100644 changelogs/fragments/83-ee.yml create mode 100644 meta/ee-requirements.txt create mode 100644 meta/execution-environment.yml create mode 100644 tests/ee/all.yml create mode 100644 tests/ee/roles/filter_quoting/aliases create mode 100644 tests/ee/roles/filter_quoting/tasks/main.yml create mode 100644 tests/ee/roles/smoke/tasks/main.yml diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml new file mode 100644 index 0000000..ce5bc91 --- /dev/null +++ b/.github/workflows/ee.yml @@ -0,0 +1,113 @@ +--- +name: execution environment +on: + # Run CI against all pushes (direct commits, also merged PRs), Pull Requests + push: + branches: + - main + - stable-* + pull_request: + # Run CI once per day (at 05:15 UTC) + # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-builder + schedule: + - cron: '15 5 * * *' + +env: + NAMESPACE: community + COLLECTION_NAME: routeros + +jobs: + build: + name: Build and test EE (Ⓐ${{ matrix.runner_tag }}) + strategy: + matrix: + runner_tag: + - devel + - stable-2.12-latest + - stable-2.11-latest + - stable-2.9-latest + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.10' + + - name: Install ansible-builder and ansible-navigator + run: pip install ansible-builder ansible-navigator + + - name: Verify requirements + run: ansible-builder introspect --sanitize . + + - name: Make sure galaxy.yml has version entry + run: >- + python -c + 'import yaml ; + f = open("galaxy.yml", "rb") ; + data = yaml.safe_load(f) ; + f.close() ; + data["version"] = data.get("version") or "0.0.1" ; + f = open("galaxy.yml", "wb") ; + f.write(yaml.dump(data).encode("utf-8")) ; + f.close() ; + ' + working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} + + - name: Install collection dependencies + run: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon + # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) + # run: ansible-galaxy collection install ansible.netcommon -p . + + - name: Build collection + run: | + ansible-galaxy collection build --output-path ../../../ + working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} + + - name: Create files for building execution environment + run: | + COLLECTION_FILENAME="$(ls "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)" + + # EE config + cat > execution-environment.yml < requirements.yml < + ansible-navigator run + --mode stdout + --pull-policy never + --set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true + --execution-environment-image test-ee:latest + all.yml + working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee diff --git a/changelogs/fragments/83-ee.yml b/changelogs/fragments/83-ee.yml new file mode 100644 index 0000000..1358503 --- /dev/null +++ b/changelogs/fragments/83-ee.yml @@ -0,0 +1,2 @@ +minor_changes: + - "Prepare collection for inclusion in an Execution Environment by declaring its dependencies (https://github.com/ansible-collections/community.routeros/pull/83)." diff --git a/meta/ee-requirements.txt b/meta/ee-requirements.txt new file mode 100644 index 0000000..f3d520b --- /dev/null +++ b/meta/ee-requirements.txt @@ -0,0 +1 @@ +librouteros diff --git a/meta/execution-environment.yml b/meta/execution-environment.yml new file mode 100644 index 0000000..c899493 --- /dev/null +++ b/meta/execution-environment.yml @@ -0,0 +1,4 @@ +--- +version: 1 +dependencies: + python: meta/ee-requirements.txt diff --git a/tests/ee/all.yml b/tests/ee/all.yml new file mode 100644 index 0000000..1a937d4 --- /dev/null +++ b/tests/ee/all.yml @@ -0,0 +1,13 @@ +- hosts: localhost + tasks: + - name: Find all roles + find: + paths: + - "{{ playbook_dir ~ '/roles/' }}" + file_type: directory + depth: 1 + register: result + - name: Include all roles + include_role: + name: "{{ item }}" + loop: "{{ result.files | map(attribute='path') | map('regex_replace', '.*/', '') | sort }}" diff --git a/tests/ee/roles/filter_quoting/aliases b/tests/ee/roles/filter_quoting/aliases new file mode 100644 index 0000000..54ea5a3 --- /dev/null +++ b/tests/ee/roles/filter_quoting/aliases @@ -0,0 +1,2 @@ +shippable/posix/group1 +skip/python2.6 diff --git a/tests/ee/roles/filter_quoting/tasks/main.yml b/tests/ee/roles/filter_quoting/tasks/main.yml new file mode 100644 index 0000000..a871cfc --- /dev/null +++ b/tests/ee/roles/filter_quoting/tasks/main.yml @@ -0,0 +1,59 @@ +--- +- name: "Test split filter" + assert: + that: + - "'' | community.routeros.split == []" + - "'foo bar' | community.routeros.split == ['foo', 'bar']" + - > + 'foo bar="a b c"' | community.routeros.split == ['foo', 'bar=a b c'] + +- name: "Test split filter error handling" + set_fact: + test: >- + {{ 'a="' | community.routeros.split }} + ignore_errors: true + register: result + +- name: "Verify split filter error handling" + assert: + that: + - >- + result.msg == "Unexpected end of string during escaped parameter" + +- name: "Test quote_argument filter" + assert: + that: + - > + 'a=' | community.routeros.quote_argument == 'a=""' + - > + 'a=b' | community.routeros.quote_argument == 'a=b' + - > + 'a=b c' | community.routeros.quote_argument == 'a="b c"' + - > + 'a=""' | community.routeros.quote_argument == 'a="\\"\\""' + +- name: "Test quote_argument_value filter" + assert: + that: + - > + '' | community.routeros.quote_argument_value == '""' + - > + 'foo' | community.routeros.quote_argument_value == 'foo' + - > + '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo bar\\""' + +- name: "Test join filter" + assert: + that: + - > + ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c d"' + +- name: "Test list_to_dict filter" + assert: + that: + - > + ['a=', 'b=c'] | community.routeros.list_to_dict == {'a': '', 'b': 'c'} + - > + ['a=', 'b=c'] | community.routeros.list_to_dict(skip_empty_values=True) == {'b': 'c'} + - > + ['a', 'b=c'] | community.routeros.list_to_dict(require_assignment=False) == {'a': none, 'b': 'c'} diff --git a/tests/ee/roles/smoke/tasks/main.yml b/tests/ee/roles/smoke/tasks/main.yml new file mode 100644 index 0000000..ff160de --- /dev/null +++ b/tests/ee/roles/smoke/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: Run api module + community.routeros.api: + username: foo + password: bar + hostname: localhost + path: ip address + ignore_errors: true + register: result + +- name: Validate result + assert: + that: + - result is failed + - "'error: [Errno 111] Connection refused' in result.msg" + +- name: Run command module + community.routeros.command: + commands: + - /ip address print + vars: + ansible_host: localhost + ansible_connection: ansible.netcommon.network_cli + ansible_network_os: community.routeros.routeros + ansible_user: foo + ansible_ssh_pass: bar + ansible_ssh_port: 12349 + ignore_errors: true + register: result + +- name: Validate result + assert: + that: + - result is failed + - "'Unable to connect to port 12349 ' in result.msg" From 0815b11bbfd5be915aa96bb66b9ea8af04f42444 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 16 Apr 2022 07:09:02 +0200 Subject: [PATCH 028/365] Increase verbosity for EE tests (#84) * Increase verbosity for EE tests. * 2.9 compatibility. --- .github/workflows/ee.yml | 1 + tests/ee/all.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index ce5bc91..25600dc 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -109,5 +109,6 @@ jobs: --pull-policy never --set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true --execution-environment-image test-ee:latest + -v all.yml working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee diff --git a/tests/ee/all.yml b/tests/ee/all.yml index 1a937d4..7593912 100644 --- a/tests/ee/all.yml +++ b/tests/ee/all.yml @@ -3,7 +3,7 @@ - name: Find all roles find: paths: - - "{{ playbook_dir ~ '/roles/' }}" + - "{{ (playbook_dir | default('.')) ~ '/roles' }}" file_type: directory depth: 1 register: result From d56410b468d580da1e7f5661c96d40284b55f0a8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 27 Apr 2022 09:26:03 +0200 Subject: [PATCH 029/365] Accept new error. (#85) --- tests/ee/roles/smoke/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ee/roles/smoke/tasks/main.yml b/tests/ee/roles/smoke/tasks/main.yml index ff160de..484b9ce 100644 --- a/tests/ee/roles/smoke/tasks/main.yml +++ b/tests/ee/roles/smoke/tasks/main.yml @@ -32,4 +32,4 @@ assert: that: - result is failed - - "'Unable to connect to port 12349 ' in result.msg" + - "'Unable to connect to port 12349 ' in result.msg or 'ssh connect failed: Connection refused' in result.msg" From 02ecc0ca9d00c2b04ae18d90d55daf0499f88f43 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 30 Apr 2022 16:40:59 +0200 Subject: [PATCH 030/365] Add filter documentation (#87) * Add filter documentation. * Update no-unwanted-files sanity check. --- plugins/filter/join.yml | 26 ++++++++++++++++++ plugins/filter/list_to_dict.yml | 36 +++++++++++++++++++++++++ plugins/filter/quote_argument.yml | 25 +++++++++++++++++ plugins/filter/quote_argument_value.yml | 25 +++++++++++++++++ plugins/filter/split.yml | 26 ++++++++++++++++++ tests/sanity/extra/no-unwanted-files.py | 14 ++++++++++ 6 files changed, 152 insertions(+) create mode 100644 plugins/filter/join.yml create mode 100644 plugins/filter/list_to_dict.yml create mode 100644 plugins/filter/quote_argument.yml create mode 100644 plugins/filter/quote_argument_value.yml create mode 100644 plugins/filter/split.yml diff --git a/plugins/filter/join.yml b/plugins/filter/join.yml new file mode 100644 index 0000000..1642ef1 --- /dev/null +++ b/plugins/filter/join.yml @@ -0,0 +1,26 @@ +DOCUMENTATION: + name: join + short_description: Join a list of arguments to a command + version_added: 2.0.0 + description: + - Join and quotes a list of arguments to a command. + options: + _input: + description: + - A list of arguments to quote and join. + type: list + elements: string + required: true + author: + - Felix Fontein (@felixfontein) + +EXAMPLES: | + - name: Join arguments for a RouterOS CLI command + ansible.builtin.set_fact: + arguments: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.join }}" + # Should result in 'foo=bar comment="foo is bar"' + +RETURN: + _value: + description: The joined and quoted result. + type: string diff --git a/plugins/filter/list_to_dict.yml b/plugins/filter/list_to_dict.yml new file mode 100644 index 0000000..bfac7c4 --- /dev/null +++ b/plugins/filter/list_to_dict.yml @@ -0,0 +1,36 @@ +DOCUMENTATION: + name: list_to_dict + short_description: Convert a list of arguments to a dictionary + version_added: 2.0.0 + description: + - Convert a list of arguments to a dictionary. + options: + _input: + description: + - A list of assignments. Can be the result of the C(community.routeros.split) filter. + type: list + elements: string + required: true + require_assignment: + description: + - Allows to accept arguments without values when set to C(false). + type: boolean + default: true + skip_empty_values: + description: + - Allows to skip arguments whose value is empty when set to C(true). + type: boolean + default: false + author: + - Felix Fontein (@felixfontein) + +EXAMPLES: | + - name: Convert a list to a dictionary + ansible.builtin.set_fact: + dictionary: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict }}" + # dictionary == {'foo': 'bar', 'comment': 'foo is bar'} + +RETURN: + _value: + description: A dictionary representation of the input data. + type: dictionary diff --git a/plugins/filter/quote_argument.yml b/plugins/filter/quote_argument.yml new file mode 100644 index 0000000..4389fc5 --- /dev/null +++ b/plugins/filter/quote_argument.yml @@ -0,0 +1,25 @@ +DOCUMENTATION: + name: quote_argument + short_description: Quote an argument + version_added: 2.0.0 + description: + - Quote an argument. + options: + _input: + description: + - An argument to quote. + type: string + required: true + author: + - Felix Fontein (@felixfontein) + +EXAMPLES: | + - name: Quote a RouterOS CLI command argument + ansible.builtin.set_fact: + quoted: "{{ 'comment=this is a "comment"' | community.routeros.quote_argument }}" + # Should result in 'comment="this is a \"comment\""' + +RETURN: + _value: + description: The quoted argument. + type: string diff --git a/plugins/filter/quote_argument_value.yml b/plugins/filter/quote_argument_value.yml new file mode 100644 index 0000000..65f50d0 --- /dev/null +++ b/plugins/filter/quote_argument_value.yml @@ -0,0 +1,25 @@ +DOCUMENTATION: + name: quote_argument_value + short_description: Quote an argument value + version_added: 2.0.0 + description: + - Quote an argument value. + options: + _input: + description: + - An argument value to quote. + type: string + required: true + author: + - Felix Fontein (@felixfontein) + +EXAMPLES: | + - name: Quote a RouterOS CLI command argument's value + ansible.builtin.set_fact: + quoted: "{{ 'this is a "comment"' | community.routeros.quote_argument_value }}" + # Should result in '"this is a \"comment\""' + +RETURN: + _value: + description: The quoted argument value. + type: string diff --git a/plugins/filter/split.yml b/plugins/filter/split.yml new file mode 100644 index 0000000..d56b820 --- /dev/null +++ b/plugins/filter/split.yml @@ -0,0 +1,26 @@ +DOCUMENTATION: + name: split + short_description: Split a command into arguments + version_added: 2.0.0 + description: + - Split a command into arguments. + options: + _input: + description: + - A command. + type: string + required: true + author: + - Felix Fontein (@felixfontein) + +EXAMPLES: | + - name: Split command into list of arguments + ansible.builtin.set_fact: + argument_list: "{{ 'foo=bar comment="foo is bar" baz' | community.routeros.split }}" + # Should result in ['foo=bar', 'comment=foo is bar', 'baz'] + +RETURN: + _value: + description: The list of arguments. + type: list + elements: string diff --git a/tests/sanity/extra/no-unwanted-files.py b/tests/sanity/extra/no-unwanted-files.py index 49806f2..4522f77 100755 --- a/tests/sanity/extra/no-unwanted-files.py +++ b/tests/sanity/extra/no-unwanted-files.py @@ -6,6 +6,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type import os +import os.path import sys @@ -26,6 +27,11 @@ def main(): skip_directories = ( ) + yaml_directories = ( + 'plugins/test/', + 'plugins/filter/', + ) + for path in paths: if path in skip_paths: continue @@ -33,8 +39,16 @@ def main(): if any(path.startswith(skip_directory) for skip_directory in skip_directories): continue + if os.path.islink(path): + print('%s: is a symbolic link' % (path, )) + elif not os.path.isfile(path): + print('%s: is not a regular file' % (path, )) + ext = os.path.splitext(path)[1] + if ext in ('.yml', ) and any(path.startswith(yaml_directory) for yaml_directory in yaml_directories): + continue + if ext not in allowed_extensions: print('%s: extension must be one of: %s' % (path, ', '.join(allowed_extensions))) From a90c6965891261553aa50719ce9994fe48a64516 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 9 May 2022 22:09:08 +0200 Subject: [PATCH 031/365] Correctly handle \_ escape sequence. (#89) --- changelogs/fragments/89-quoting.yml | 2 ++ plugins/module_utils/quoting.py | 2 +- tests/ee/roles/filter_quoting/tasks/main.yml | 6 +++--- .../targets/filter_quoting/tasks/main.yml | 6 +++--- tests/unit/plugins/module_utils/test_quoting.py | 17 +++++++++-------- 5 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 changelogs/fragments/89-quoting.yml diff --git a/changelogs/fragments/89-quoting.yml b/changelogs/fragments/89-quoting.yml new file mode 100644 index 0000000..bec8340 --- /dev/null +++ b/changelogs/fragments/89-quoting.yml @@ -0,0 +1,2 @@ +bugfixes: + - "quoting and unquoting filter plugins, api module - handle the escape sequence ``\\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89)." diff --git a/plugins/module_utils/quoting.py b/plugins/module_utils/quoting.py index 61d67da..5524de4 100644 --- a/plugins/module_utils/quoting.py +++ b/plugins/module_utils/quoting.py @@ -21,7 +21,7 @@ ESCAPE_SEQUENCES = { b'\\': b'\\', b'?': b'?', b'$': b'$', - b'_': b'_', + b'_': b' ', b'a': b'\a', b'b': b'\b', b'f': b'\xFF', diff --git a/tests/ee/roles/filter_quoting/tasks/main.yml b/tests/ee/roles/filter_quoting/tasks/main.yml index a871cfc..bebed37 100644 --- a/tests/ee/roles/filter_quoting/tasks/main.yml +++ b/tests/ee/roles/filter_quoting/tasks/main.yml @@ -28,7 +28,7 @@ - > 'a=b' | community.routeros.quote_argument == 'a=b' - > - 'a=b c' | community.routeros.quote_argument == 'a="b c"' + 'a=b c' | community.routeros.quote_argument == 'a="b\\_c"' - > 'a=""' | community.routeros.quote_argument == 'a="\\"\\""' @@ -40,13 +40,13 @@ - > 'foo' | community.routeros.quote_argument_value == 'foo' - > - '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo bar\\""' + '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo\\_bar\\""' - name: "Test join filter" assert: that: - > - ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c d"' + ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c\\_d"' - name: "Test list_to_dict filter" assert: diff --git a/tests/integration/targets/filter_quoting/tasks/main.yml b/tests/integration/targets/filter_quoting/tasks/main.yml index a871cfc..bebed37 100644 --- a/tests/integration/targets/filter_quoting/tasks/main.yml +++ b/tests/integration/targets/filter_quoting/tasks/main.yml @@ -28,7 +28,7 @@ - > 'a=b' | community.routeros.quote_argument == 'a=b' - > - 'a=b c' | community.routeros.quote_argument == 'a="b c"' + 'a=b c' | community.routeros.quote_argument == 'a="b\\_c"' - > 'a=""' | community.routeros.quote_argument == 'a="\\"\\""' @@ -40,13 +40,13 @@ - > 'foo' | community.routeros.quote_argument_value == 'foo' - > - '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo bar\\""' + '"foo bar"' | community.routeros.quote_argument_value == '"\\"foo\\_bar\\""' - name: "Test join filter" assert: that: - > - ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c d"' + ['a=', 'b=c d'] | community.routeros.join == 'a="" b="c\\_d"' - name: "Test list_to_dict filter" assert: diff --git a/tests/unit/plugins/module_utils/test_quoting.py b/tests/unit/plugins/module_utils/test_quoting.py index 15d6142..fe13b66 100644 --- a/tests/unit/plugins/module_utils/test_quoting.py +++ b/tests/unit/plugins/module_utils/test_quoting.py @@ -34,7 +34,7 @@ TEST_PARSE_ARGUMENT_VALUE = [ (r'"\\"', {}, ('\\', 4)), (r'"\?"', {}, ('?', 4)), (r'"\$"', {}, ('$', 4)), - (r'"\_"', {}, ('_', 4)), + (r'"\_"', {}, (' ', 4)), (r'"\a"', {}, ('\a', 4)), (r'"\b"', {}, ('\b', 4)), (r'"\f"', {}, (to_native(b'\xff'), 4)), @@ -165,7 +165,7 @@ def test_convert_list_to_dictionary_errors(list, kwargs, message): TEST_JOIN_ROUTEROS_COMMAND = [ - (['a=b', 'c=d=e', 'e=', 'f', 'g=h i j', 'h="h"'], r'a=b c="d=e" e="" f g="h i j" h="\"h\""'), + (['a=b', 'c=d=e', 'e=', 'f', 'g=h i j', 'h="h"'], r'a=b c="d=e" e="" f g="h\_i\_j" h="\"h\""'), ] @@ -180,8 +180,8 @@ TEST_QUOTE_ROUTEROS_ARGUMENT = [ (r'', r''), (r'a', r'a'), (r'a=b', r'a=b'), - (r'a=b c', r'a="b c"'), - (r'a="b c"', r'a="\"b c\""'), + (r'a=b c', r'a="b\_c"'), + (r'a="b c"', r'a="\"b\_c\""'), (r"a='b", "a=\"'b\""), (r"a=b'", "a=\"b'\""), (r'a=""', r'a="\"\""'), @@ -212,19 +212,20 @@ def test_quote_routeros_argument_errors(argument, message): TEST_QUOTE_ROUTEROS_ARGUMENT_VALUE = [ (r'', r'""'), (r";", r'";"'), - (r" ", r'" "'), + (r" ", r'"\_"'), (r"=", r'"="'), (r'a', r'a'), (r'a=b', r'"a=b"'), - (r'b c', r'"b c"'), - (r'"b c"', r'"\"b c\""'), + (r'b c', r'"b\_c"'), + (r'"b c"', r'"\"b\_c\""'), ("'b", "\"'b\""), ("b'", "\"b'\""), ('"', r'"\""'), ('\\', r'"\\"'), ('?', r'"\?"'), ('$', r'"\$"'), - ('_', r'"\_"'), + ('_', r'_'), + (' ', r'"\_"'), ('\a', r'"\a"'), ('\b', r'"\b"'), # (to_native(b'\xff'), r'"\f"'), From 3d80ccec5f0d9000d2ccc50d1a682cf3a7f59b7f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 12 May 2022 16:17:43 +0200 Subject: [PATCH 032/365] Add api_facts module (#88) * Add API docs fragment. * Improve documentation. * Move API code to api module_utils. * Improve docs. * Add api_facts module. Does not yet support 'config'. I'm not sure whether that's actually possible with the API. * Convert subnet to integer if possible. * Cleanup. * Linting and fix tests. * Remove things that make no sense. * Simplify code. * Add basic tests. * Lint. --- plugins/doc_fragments/api.py | 72 ++ plugins/module_utils/api.py | 108 +++ plugins/modules/api.py | 144 +--- plugins/modules/api_facts.py | 483 ++++++++++++ plugins/modules/facts.py | 102 +-- tests/ee/roles/smoke/tasks/main.yml | 2 +- tests/unit/plugins/modules/fake_api.py | 115 +++ tests/unit/plugins/modules/test_api.py | 103 +-- tests/unit/plugins/modules/test_api_facts.py | 766 +++++++++++++++++++ 9 files changed, 1618 insertions(+), 277 deletions(-) create mode 100644 plugins/doc_fragments/api.py create mode 100644 plugins/module_utils/api.py create mode 100644 plugins/modules/api_facts.py create mode 100644 tests/unit/plugins/modules/fake_api.py create mode 100644 tests/unit/plugins/modules/test_api_facts.py diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py new file mode 100644 index 0000000..f436d64 --- /dev/null +++ b/plugins/doc_fragments/api.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Nikolay Dachev +# GNU General Public License v3.0+ https://www.gnu.org/licenses/gpl-3.0.txt + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + + DOCUMENTATION = r''' +options: + hostname: + description: + - RouterOS hostname API. + required: true + type: str + username: + description: + - RouterOS login user. + required: true + type: str + password: + description: + - RouterOS user password. + required: true + type: str + tls: + description: + - If is set TLS will be used for RouterOS API connection. + required: false + type: bool + default: false + aliases: + - ssl + port: + description: + - RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection. + - Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API. + type: int + validate_certs: + description: + - Set to C(false) to skip validation of TLS certificates. + - See also I(validate_cert_hostname). Only used when I(tls=true). + - B(Note:) instead of simply deactivating certificate validations to "make things work", + please consider creating your own CA certificate and using it to sign certificates used + for your router. You can tell the module about your CA certificate with the I(ca_path) + option. + type: bool + default: true + version_added: 1.2.0 + validate_cert_hostname: + description: + - Set to C(true) to validate hostnames in certificates. + - See also I(validate_certs). Only used when I(tls=true) and I(validate_certs=true). + type: bool + default: false + version_added: 1.2.0 + ca_path: + description: + - PEM formatted file that contains a CA certificate to be used for certificate validation. + - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). + type: path + version_added: 1.2.0 +requirements: + - librouteros + - Python >= 3.6 (for librouteros) +seealso: + - ref: ansible_collections.community.routeros.docsite.api-guide + description: How to connect to RouterOS devices with the RouterOS API +''' diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py new file mode 100644 index 0000000..f8b839f --- /dev/null +++ b/plugins/module_utils/api.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2022, Felix Fontein (@felixfontein) +# Copyright: (c) 2020, Nikolay Dachev +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +from ansible.module_utils.basic import missing_required_lib +from ansible.module_utils.common.text.converters import to_native + +import re +import ssl +import traceback + +LIB_IMP_ERR = None +try: + from librouteros import connect + from librouteros.exceptions import LibRouterosError + HAS_LIB = True +except Exception as e: + HAS_LIB = False + LIB_IMP_ERR = traceback.format_exc() + + +def check_has_library(module): + if not HAS_LIB: + module.fail_json( + msg=missing_required_lib('librouteros'), + exception=LIB_IMP_ERR, + ) + + +def api_argument_spec(): + return dict( + username=dict(type='str', required=True), + password=dict(type='str', required=True, no_log=True), + hostname=dict(type='str', required=True), + port=dict(type='int'), + tls=dict(type='bool', default=False, aliases=['ssl']), + validate_certs=dict(type='bool', default=True), + validate_cert_hostname=dict(type='bool', default=False), + ca_path=dict(type='path'), + ) + + +def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path): + '''Connect to RouterOS API.''' + if not port: + if use_tls: + port = 8729 + else: + port = 8728 + try: + if use_tls: + ctx = ssl.create_default_context(cafile=ca_path) + wrap_context = ctx.wrap_socket + if not validate_certs: + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + elif not validate_cert_hostname: + ctx.check_hostname = False + else: + # Since librouteros doesn't pass server_hostname, + # we have to do this ourselves: + def wrap_context(*args, **kwargs): + kwargs.pop('server_hostname', None) + return ctx.wrap_socket(*args, server_hostname=host, **kwargs) + api = connect( + username=username, + password=password, + host=host, + ssl_wrapper=wrap_context, + port=port, + ) + else: + api = connect( + username=username, + password=password, + host=host, + port=port, + ) + except Exception as e: + connection = { + 'username': username, + 'hostname': host, + 'port': port, + 'ssl': use_tls, + 'status': 'Error while connecting: %s' % to_native(e), + } + module.fail_json(msg=connection['status'], connection=connection) + return api + + +def create_api(module): + return _ros_api_connect( + module, + module.params['username'], + module.params['password'], + module.params['hostname'], + module.params['port'], + module.params['tls'], + module.params['validate_certs'], + module.params['validate_cert_hostname'], + module.params['ca_path'], + ) diff --git a/plugins/modules/api.py b/plugins/modules/api.py index e4e716c..dc58ca5 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -13,43 +13,14 @@ module: api author: "Nikolay Dachev (@NikolayDachev)" short_description: Ansible module for RouterOS API description: - - Ansible module for RouterOS API with python librouteros. - - This module can add, remove, update, query and execute arbitrary command in routeros via API. + - Ansible module for RouterOS API with the Python C(librouteros) library. + - This module can add, remove, update, query and execute arbitrary command in RouterOS via API. notes: - I(add), I(remove), I(update), I(cmd) and I(query) are mutually exclusive. - I(check_mode) is not supported. -requirements: - - librouteros - - Python >= 3.6 (for librouteros) +extends_documentation_fragment: + - community.routeros.api options: - hostname: - description: - - RouterOS hostname API. - required: true - type: str - username: - description: - - RouterOS login user. - required: true - type: str - password: - description: - - RouterOS user password. - required: true - type: str - tls: - description: - - If is set TLS will be used for RouterOS API connection. - required: false - type: bool - default: false - aliases: - - ssl - port: - description: - - RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection. - - Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API. - type: int path: description: - Main path for all other arguments. @@ -95,33 +66,7 @@ options: - Example path C(system script) and cmd C(run .id=*03) is equivalent in RouterOS CLI C(/system script run number=0). - Example path C(ip address) and cmd C(print) is equivalent in RouterOS CLI C(/ip address print). type: str - validate_certs: - description: - - Set to C(false) to skip validation of TLS certificates. - - See also I(validate_cert_hostname). Only used when I(tls=true). - - B(Note:) instead of simply deactivating certificate validations to "make things work", - please consider creating your own CA certificate and using it to sign certificates used - for your router. You can tell the module about your CA certificate with the I(ca_path) - option. - type: bool - default: true - version_added: 1.2.0 - validate_cert_hostname: - description: - - Set to C(true) to validate hostnames in certificates. - - See also I(validate_certs). Only used when I(tls=true) and I(validate_certs=true). - type: bool - default: false - version_added: 1.2.0 - ca_path: - description: - - PEM formatted file that contains a CA certificate to be used for certificate validation. - - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). - type: path - version_added: 1.2.0 seealso: - - ref: ansible_collections.community.routeros.docsite.api-guide - description: How to connect to RouterOS devices with the RouterOS API - ref: ansible_collections.community.routeros.docsite.quoting description: How to quote and unquote commands and arguments ''' @@ -275,58 +220,44 @@ from ansible_collections.community.routeros.plugins.module_utils.quoting import split_routeros_command, ) +from ansible_collections.community.routeros.plugins.module_utils.api import ( + api_argument_spec, + check_has_library, + create_api, +) + import re import ssl import traceback -LIB_IMP_ERR = None try: - from librouteros import connect from librouteros.exceptions import LibRouterosError from librouteros.query import Key - HAS_LIB = True -except Exception as e: - HAS_LIB = False - LIB_IMP_ERR = traceback.format_exc() +except Exception: + # Handled in api module_utils + pass class ROS_api_module: def __init__(self): module_args = dict( - username=dict(type='str', required=True), - password=dict(type='str', required=True, no_log=True), - hostname=dict(type='str', required=True), - port=dict(type='int'), - tls=dict(type='bool', default=False, aliases=['ssl']), path=dict(type='str', required=True), add=dict(type='str'), remove=dict(type='str'), update=dict(type='str'), cmd=dict(type='str'), query=dict(type='str'), - validate_certs=dict(type='bool', default=True), - validate_cert_hostname=dict(type='bool', default=False), - ca_path=dict(type='path'), ) + module_args.update(api_argument_spec()) self.module = AnsibleModule(argument_spec=module_args, supports_check_mode=False, mutually_exclusive=(('add', 'remove', 'update', 'cmd', 'query'),),) - if not HAS_LIB: - self.module.fail_json(msg=missing_required_lib("librouteros"), - exception=LIB_IMP_ERR) + check_has_library(self.module) - self.api = self.ros_api_connect(self.module.params['username'], - self.module.params['password'], - self.module.params['hostname'], - self.module.params['port'], - self.module.params['tls'], - self.module.params['validate_certs'], - self.module.params['validate_cert_hostname'], - self.module.params['ca_path'], - ) + self.api = create_api(self.module) self.path = self.module.params['path'].split() self.add = self.module.params['add'] @@ -497,49 +428,6 @@ class ROS_api_module: self.result['message'].append("%s" % e) self.return_result(False, False) - def ros_api_connect(self, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path): - # connect to routeros api - conn_status = {"connection": {"username": username, - "hostname": host, - "port": port, - "ssl": use_tls, - "status": "Connected"}} - try: - if use_tls: - if not port: - port = 8729 - conn_status["connection"]["port"] = port - ctx = ssl.create_default_context(cafile=ca_path) - wrap_context = ctx.wrap_socket - if not validate_certs: - ctx.check_hostname = False - ctx.verify_mode = ssl.CERT_NONE - elif not validate_cert_hostname: - ctx.check_hostname = False - else: - # Since librouteros doesn't pass server_hostname, - # we have to do this ourselves: - def wrap_context(*args, **kwargs): - kwargs.pop('server_hostname', None) - return ctx.wrap_socket(*args, server_hostname=host, **kwargs) - api = connect(username=username, - password=password, - host=host, - ssl_wrapper=wrap_context, - port=port) - else: - if not port: - port = 8728 - conn_status["connection"]["port"] = port - api = connect(username=username, - password=password, - host=host, - port=port) - except Exception as e: - conn_status["connection"]["status"] = "error: %s" % e - self.module.fail_json(msg=to_native([conn_status])) - return api - def main(): diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py new file mode 100644 index 0000000..b5d0e17 --- /dev/null +++ b/plugins/modules/api_facts.py @@ -0,0 +1,483 @@ +#!/usr/bin/python + +# Copyright: (c) 2022, Felix Fontein +# Copyright: (c) 2020, Nikolay Dachev +# Copyright: (c) 2018, Egor Zaitsev (@heuels) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: api_facts +author: + - "Egor Zaitsev (@heuels)" + - "Nikolay Dachev (@NikolayDachev)" + - "Felix Fontein (@felixfontein)" +version_added: 2.1.0 +short_description: Collect facts from remote devices running MikroTik RouterOS using the API +description: + - Collects a base set of device facts from a remote device that + is running RouterOS. This module prepends all of the + base network fact keys with C(ansible_net_). The facts + module will always collect a base set of facts from the device + and can enable or disable collection of additional facts. + - As opposed to the M(community.routeros.facts) module, it uses the + RouterOS API, similar to the M(community.routeros.api) module. +extends_documentation_fragment: + - community.routeros.api +options: + gather_subset: + description: + - When supplied, this argument will restrict the facts collected + to a given subset. Possible values for this argument include + C(all), C(hardware), C(interfaces), and C(routing). + - Can specify a list of values to include a larger subset. + Values can also be used with an initial C(!) to specify that a + specific subset should not be collected. + required: false + default: 'all' + type: list + elements: str +seealso: + - module: community.routeros.facts + - module: community.routeros.api +''' + +EXAMPLES = """ +- name: Collect all facts from the device + community.routeros.api_facts: + hostname: 192.168.88.1 + username: admin + password: password + gather_subset: all + +- name: Do not collect hardware facts + community.routeros.api_facts: + hostname: 192.168.88.1 + username: admin + password: password + gather_subset: + - "!hardware" +""" + +RETURN = """ +ansible_facts: + description: "Dictionary of IP geolocation facts for a host's IP address." + returned: always + type: dict + contains: + ansible_net_gather_subset: + description: The list of fact subsets collected from the device. + returned: always + type: list + + # default + ansible_net_model: + description: The model name returned from the device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_serialnum: + description: The serial number of the remote device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_version: + description: The operating system version running on the remote device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_hostname: + description: The configured hostname of the device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_arch: + description: The CPU architecture of the device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_uptime: + description: The uptime of the device. + returned: I(gather_subset) contains C(default) + type: str + ansible_net_cpu_load: + description: Current CPU load. + returned: I(gather_subset) contains C(default) + type: str + + # hardware + ansible_net_spacefree_mb: + description: The available disk space on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) + type: dict + ansible_net_spacetotal_mb: + description: The total disk space on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) + type: dict + ansible_net_memfree_mb: + description: The available free memory on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) + type: int + ansible_net_memtotal_mb: + description: The total memory on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) + type: int + + # interfaces + ansible_net_all_ipv4_addresses: + description: All IPv4 addresses configured on the device. + returned: I(gather_subset) contains C(interfaces) + type: list + ansible_net_all_ipv6_addresses: + description: All IPv6 addresses configured on the device. + returned: I(gather_subset) contains C(interfaces) + type: list + ansible_net_interfaces: + description: A hash of all interfaces running on the system. + returned: I(gather_subset) contains C(interfaces) + type: dict + ansible_net_neighbors: + description: The list of neighbors from the remote device. + returned: I(gather_subset) contains C(interfaces) + type: dict + + # routing + ansible_net_bgp_peer: + description: A dictionary with BGP peer information. + returned: I(gather_subset) contains C(routing) + type: dict + ansible_net_bgp_vpnv4_route: + description: A dictionary with BGP vpnv4 route information. + returned: I(gather_subset) contains C(routing) + type: dict + ansible_net_bgp_instance: + description: A dictionary with BGP instance information. + returned: I(gather_subset) contains C(routing) + type: dict + ansible_net_route: + description: A dictionary for routes in all routing tables. + returned: I(gather_subset) contains C(routing) + type: dict + ansible_net_ospf_instance: + description: A dictionary with OSPF instances. + returned: I(gather_subset) contains C(routing) + type: dict + ansible_net_ospf_neighbor: + description: A dictionary with OSPF neighbors. + returned: I(gather_subset) contains C(routing) + type: dict +""" +import re + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.six import iteritems +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils.api import ( + api_argument_spec, + check_has_library, + create_api, +) + +try: + from librouteros.exceptions import LibRouterosError +except Exception: + # Handled in api module_utils + pass + + +class FactsBase(object): + + COMMANDS = [] + + def __init__(self, module, api): + self.module = module + self.api = api + self.facts = {} + self.responses = None + + def populate(self): + self.responses = [] + for path in self.COMMANDS: + self.responses.append(self.query_path(path)) + + def query_path(self, path): + api_path = self.api.path() + for part in path: + api_path = api_path.join(part) + try: + return list(api_path) + except LibRouterosError as e: + self.module.warn('Error while querying path {path}: {error}'.format( + path=' '.join(path), + error=to_native(e), + )) + return [] + + +class Default(FactsBase): + + COMMANDS = [ + ['system', 'identity'], + ['system', 'resource'], + ['system', 'routerboard'], + ] + + def populate(self): + super(Default, self).populate() + data = self.responses[0] + if data: + self.facts['hostname'] = data[0].get('name') + data = self.responses[1] + if data: + self.facts['version'] = data[0].get('version') + self.facts['arch'] = data[0].get('architecture-name') + self.facts['uptime'] = data[0].get('uptime') + self.facts['cpu_load'] = data[0].get('cpu-load') + data = self.responses[2] + if data: + self.facts['model'] = data[0].get('model') + self.facts['serialnum'] = data[0].get('serial-number') + + +class Hardware(FactsBase): + + COMMANDS = [ + ['system', 'resource'], + ] + + def populate(self): + super(Hardware, self).populate() + data = self.responses[0] + if data: + self.parse_filesystem_info(data[0]) + self.parse_memory_info(data[0]) + + def parse_filesystem_info(self, data): + self.facts['spacefree_mb'] = self.to_megabytes(data.get('free-hdd-space')) + self.facts['spacetotal_mb'] = self.to_megabytes(data.get('total-hdd-space')) + + def parse_memory_info(self, data): + self.facts['memfree_mb'] = self.to_megabytes(data.get('free-memory')) + self.facts['memtotal_mb'] = self.to_megabytes(data.get('total-memory')) + + def to_megabytes(self, value): + if value is None: + return None + return float(value) / 1024 / 1024 + + +class Interfaces(FactsBase): + + COMMANDS = [ + ['interface'], + ['ip', 'address'], + ['ipv6', 'address'], + ['ip', 'neighbor'], + ] + + def populate(self): + super(Interfaces, self).populate() + + self.facts['interfaces'] = {} + self.facts['all_ipv4_addresses'] = [] + self.facts['all_ipv6_addresses'] = [] + self.facts['neighbors'] = [] + + data = self.responses[0] + if data: + interfaces = self.parse_interfaces(data) + self.populate_interfaces(interfaces) + + data = self.responses[1] + if data: + data = self.parse_detail(data) + self.populate_addresses(data, 'ipv4') + + data = self.responses[2] + if data: + data = self.parse_detail(data) + self.populate_addresses(data, 'ipv6') + + data = self.responses[3] + if data: + self.facts['neighbors'] = list(self.parse_detail(data)) + + def populate_interfaces(self, data): + for key, value in iteritems(data): + self.facts['interfaces'][key] = value + + def populate_addresses(self, data, family): + for value in data: + key = value['interface'] + if family not in self.facts['interfaces'][key]: + self.facts['interfaces'][key][family] = [] + addr, subnet = value['address'].split('/') + subnet = subnet.strip() + # Try to convert subnet to an integer + try: + subnet = int(subnet) + except Exception: + pass + ip = dict(address=addr.strip(), subnet=subnet) + self.add_ip_address(addr.strip(), family) + self.facts['interfaces'][key][family].append(ip) + + def add_ip_address(self, address, family): + if family == 'ipv4': + self.facts['all_ipv4_addresses'].append(address) + else: + self.facts['all_ipv6_addresses'].append(address) + + def parse_interfaces(self, data): + facts = {} + for entry in data: + if 'name' not in entry: + continue + entry.pop('.id', None) + facts[entry['name']] = entry + return facts + + def parse_detail(self, data): + for entry in data: + if 'interface' not in entry: + continue + entry.pop('.id', None) + yield entry + + +class Routing(FactsBase): + + COMMANDS = [ + ['routing', 'bgp', 'peer'], + ['routing', 'bgp', 'vpnv4-route'], + ['routing', 'bgp', 'instance'], + ['ip', 'route'], + ['routing', 'ospf', 'instance'], + ['routing', 'ospf', 'neighbor'], + ] + + def populate(self): + super(Routing, self).populate() + self.facts['bgp_peer'] = {} + self.facts['bgp_vpnv4_route'] = {} + self.facts['bgp_instance'] = {} + self.facts['route'] = {} + self.facts['ospf_instance'] = {} + self.facts['ospf_neighbor'] = {} + data = self.responses[0] + if data: + peer = self.parse(data, 'name') + self.populate_result('bgp_peer', peer) + data = self.responses[1] + if data: + vpnv4 = self.parse(data, 'interface') + self.populate_result('bgp_vpnv4_route', vpnv4) + data = self.responses[2] + if data: + instance = self.parse(data, 'name') + self.populate_result('bgp_instance', instance) + data = self.responses[3] + if data: + route = self.parse(data, 'routing-mark', fallback='main') + self.populate_result('route', route) + data = self.responses[4] + if data: + instance = self.parse(data, 'name') + self.populate_result('ospf_instance', instance) + data = self.responses[5] + if data: + instance = self.parse(data, 'instance') + self.populate_result('ospf_neighbor', instance) + + def parse(self, data, key, fallback=None): + facts = {} + for line in data: + name = line.get(key) or fallback + line.pop('.id', None) + facts[name] = line + return facts + + def populate_result(self, name, data): + for key, value in iteritems(data): + self.facts[name][key] = value + + +FACT_SUBSETS = dict( + default=Default, + hardware=Hardware, + interfaces=Interfaces, + routing=Routing, +) + +VALID_SUBSETS = frozenset(FACT_SUBSETS.keys()) + +warnings = [] + + +def main(): + argument_spec = dict( + gather_subset=dict( + default=['all'], + type='list', + elements='str', + ) + ) + argument_spec.update(api_argument_spec()) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + check_has_library(module) + api = create_api(module) + + gather_subset = module.params['gather_subset'] + + runable_subsets = set() + exclude_subsets = set() + + for subset in gather_subset: + if subset == 'all': + runable_subsets.update(VALID_SUBSETS) + continue + + if subset.startswith('!'): + subset = subset[1:] + if subset == 'all': + exclude_subsets.update(VALID_SUBSETS) + continue + exclude = True + else: + exclude = False + + if subset not in VALID_SUBSETS: + module.fail_json(msg='Bad subset: %s' % subset) + + if exclude: + exclude_subsets.add(subset) + else: + runable_subsets.add(subset) + + if not runable_subsets: + runable_subsets.update(VALID_SUBSETS) + + runable_subsets.difference_update(exclude_subsets) + runable_subsets.add('default') + + facts = {} + facts['gather_subset'] = sorted(runable_subsets) + + instances = [] + for key in runable_subsets: + instances.append(FACT_SUBSETS[key](module, api)) + + for inst in instances: + inst.populate() + facts.update(inst.facts) + + ansible_facts = {} + for key, value in iteritems(facts): + key = 'ansible_net_%s' % key + ansible_facts[key] = value + + module.exit_json(ansible_facts=ansible_facts, warnings=warnings) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index d5589c3..3b423ca 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -21,10 +21,10 @@ options: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include - C(all), C(hardware), C(config), and C(interfaces). Can specify a list of - values to include a larger subset. Values can also be used - with an initial C(!) to specify that a specific subset should - not be collected. + C(all), C(hardware), C(config), C(interfaces), and C(routing). + - Can specify a list of values to include a larger subset. + Values can also be used with an initial C(!) to specify that a + specific subset should not be collected. required: false default: '!config' type: list @@ -52,67 +52,67 @@ EXAMPLES = """ RETURN = """ ansible_facts: - description: "Dictionary of ip geolocation facts for a host's IP address" + description: "Dictionary of IP geolocation facts for a host's IP address." returned: always type: dict contains: ansible_net_gather_subset: - description: The list of fact subsets collected from the device + description: The list of fact subsets collected from the device. returned: always type: list # default ansible_net_model: - description: The model name returned from the device - returned: always + description: The model name returned from the device. + returned: I(gather_subset) contains C(default) type: str ansible_net_serialnum: - description: The serial number of the remote device - returned: always + description: The serial number of the remote device. + returned: I(gather_subset) contains C(default) type: str ansible_net_version: - description: The operating system version running on the remote device - returned: always + description: The operating system version running on the remote device. + returned: I(gather_subset) contains C(default) type: str ansible_net_hostname: - description: The configured hostname of the device - returned: always + description: The configured hostname of the device. + returned: I(gather_subset) contains C(default) type: str ansible_net_arch: - description: The CPU architecture of the device - returned: always + description: The CPU architecture of the device. + returned: I(gather_subset) contains C(default) type: str ansible_net_uptime: - description: The uptime of the device - returned: always + description: The uptime of the device. + returned: I(gather_subset) contains C(default) type: str ansible_net_cpu_load: - description: Current CPU load - returned: always + description: Current CPU load. + returned: I(gather_subset) contains C(default) type: str # hardware ansible_net_spacefree_mb: - description: The available disk space on the remote device in MiB - returned: when hardware is configured + description: The available disk space on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) type: dict ansible_net_spacetotal_mb: - description: The total disk space on the remote device in MiB - returned: when hardware is configured + description: The total disk space on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) type: dict ansible_net_memfree_mb: - description: The available free memory on the remote device in MiB - returned: when hardware is configured + description: The available free memory on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) type: int ansible_net_memtotal_mb: - description: The total memory on the remote device in MiB - returned: when hardware is configured + description: The total memory on the remote device in MiB. + returned: I(gather_subset) contains C(hardware) type: int # config ansible_net_config: - description: The current active config from the device - returned: when config is configured + description: The current active config from the device. + returned: I(gather_subset) contains C(config) type: str ansible_net_config_nonverbose: @@ -121,52 +121,52 @@ ansible_facts: - This value is idempotent in the sense that if the facts module is run twice and the device's config was not changed between the runs, the value is identical. This is achieved by running C(/export) and stripping the timestamp from the comment in the first line. - returned: when config is configured + returned: I(gather_subset) contains C(config) type: str version_added: 1.2.0 # interfaces ansible_net_all_ipv4_addresses: - description: All IPv4 addresses configured on the device - returned: when interfaces is configured + description: All IPv4 addresses configured on the device. + returned: I(gather_subset) contains C(interfaces) type: list ansible_net_all_ipv6_addresses: - description: All IPv6 addresses configured on the device - returned: when interfaces is configured + description: All IPv6 addresses configured on the device. + returned: I(gather_subset) contains C(interfaces) type: list ansible_net_interfaces: - description: A hash of all interfaces running on the system - returned: when interfaces is configured + description: A hash of all interfaces running on the system. + returned: I(gather_subset) contains C(interfaces) type: dict ansible_net_neighbors: - description: The list of neighbors from the remote device - returned: when interfaces is configured + description: The list of neighbors from the remote device. + returned: I(gather_subset) contains C(interfaces) type: dict # routing ansible_net_bgp_peer: - description: The dict bgp peer - returned: peer information + description: A dictionary with BGP peer information. + returned: I(gather_subset) contains C(routing) type: dict ansible_net_bgp_vpnv4_route: - description: The dict bgp vpnv4 route - returned: vpnv4 route information + description: A dictionary with BGP vpnv4 route information. + returned: I(gather_subset) contains C(routing) type: dict ansible_net_bgp_instance: - description: The dict bgp instance - returned: bgp instance information + description: A dictionary with BGP instance information. + returned: I(gather_subset) contains C(routing) type: dict ansible_net_route: - description: The dict routes in all routing table - returned: routes information in all routing table + description: A dictionary for routes in all routing tables. + returned: I(gather_subset) contains C(routing) type: dict ansible_net_ospf_instance: - description: The dict ospf instance - returned: ospf instance information + description: A dictionary with OSPF instances. + returned: I(gather_subset) contains C(routing) type: dict ansible_net_ospf_neighbor: - description: The dict ospf neighbor - returned: ospf neighbor information + description: A dictionary with OSPF neighbors. + returned: I(gather_subset) contains C(routing) type: dict """ import re diff --git a/tests/ee/roles/smoke/tasks/main.yml b/tests/ee/roles/smoke/tasks/main.yml index 484b9ce..33adbff 100644 --- a/tests/ee/roles/smoke/tasks/main.yml +++ b/tests/ee/roles/smoke/tasks/main.yml @@ -12,7 +12,7 @@ assert: that: - result is failed - - "'error: [Errno 111] Connection refused' in result.msg" + - "'Error while connecting: [Errno 111] Connection refused' == result.msg" - name: Run command module community.routeros.command: diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py new file mode 100644 index 0000000..03cb6d2 --- /dev/null +++ b/tests/unit/plugins/modules/fake_api.py @@ -0,0 +1,115 @@ +# 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 + + +class FakeLibRouterosError(Exception): + def __init__(self, message): + self.message = message + super(FakeLibRouterosError, self).__init__(self.message) + + +class TrapError(FakeLibRouterosError): + def __init__(self, message="failure: already have interface with such name"): + super(TrapError, self).__init__(message) + + +# fixtures +class fake_ros_api(object): + def __init__(self, api, path): + pass + + def path(self, api, path): + fake_bridge = [{".id": "*DC", "name": "b2", "mtu": "auto", "actual-mtu": 1500, + "l2mtu": 65535, "arp": "enabled", "arp-timeout": "auto", + "mac-address": "3A:C1:90:D6:E8:44", "protocol-mode": "rstp", + "fast-forward": "true", "igmp-snooping": "false", + "auto-mac": "true", "ageing-time": "5m", "priority": + "0x8000", "max-message-age": "20s", "forward-delay": "15s", + "transmit-hold-count": 6, "vlan-filtering": "false", + "dhcp-snooping": "false", "running": "true", "disabled": "false"}] + return fake_bridge + + def arbitrary(self, api, path): + def retr(self, *args, **kwargs): + if 'name' not in kwargs.keys(): + raise TrapError(message="no such command") + dummy_test_string = '/interface/bridge add name=unit_test_brige_arbitrary' + result = "/%s/%s add name=%s" % (path[0], path[1], kwargs['name']) + return [result] + return retr + + def add(self, name): + if name == "unit_test_brige_exist": + raise TrapError + return '*A1' + + def remove(self, id): + if id != "*A1": + raise TrapError(message="no such item (4)") + return '*A1' + + def update(self, **kwargs): + if kwargs['.id'] != "*A1" or 'name' not in kwargs.keys(): + raise TrapError(message="no such item (4)") + return ["updated: {'.id': '%s' % kwargs['.id'], 'name': '%s' % kwargs['name']}"] + + def select(self, *args): + dummy_bridge = [{".id": "*A1", "name": "dummy_bridge_A1"}, + {".id": "*A2", "name": "dummy_bridge_A2"}, + {".id": "*A3", "name": "dummy_bridge_A3"}] + + result = [] + for dummy in dummy_bridge: + found = {} + for search in args: + if search in dummy.keys(): + found[search] = dummy[search] + else: + continue + if len(found.keys()) == 2: + result.append(found) + + if result: + return result + else: + return ["no results for 'interface bridge 'query' %s" % ' '.join(args)] + + def select_where(self, api, path): + api_path = Where() + return api_path + + +class Where(object): + def __init__(self): + pass + + def select(self, *args): + return self + + def where(self, *args): + return ["*A1"] + + +class Key(object): + def __init__(self, name): + self.name = name + self.str_return() + + def str_return(self): + return str(self.name) diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index cabb918..98dcd8c 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -21,107 +21,11 @@ import json import pytest from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api -class FakeLibRouterosError(Exception): - def __init__(self, message): - self.message = message - super(FakeLibRouterosError, self).__init__(self.message) - - -class TrapError(FakeLibRouterosError): - def __init__(self, message="failure: already have interface with such name"): - super(TrapError, self).__init__(message) - - -# fixtures -class fake_ros_api(object): - def __init__(self, api, path): - pass - - def path(self, api, path): - fake_bridge = [{".id": "*DC", "name": "b2", "mtu": "auto", "actual-mtu": 1500, - "l2mtu": 65535, "arp": "enabled", "arp-timeout": "auto", - "mac-address": "3A:C1:90:D6:E8:44", "protocol-mode": "rstp", - "fast-forward": "true", "igmp-snooping": "false", - "auto-mac": "true", "ageing-time": "5m", "priority": - "0x8000", "max-message-age": "20s", "forward-delay": "15s", - "transmit-hold-count": 6, "vlan-filtering": "false", - "dhcp-snooping": "false", "running": "true", "disabled": "false"}] - return fake_bridge - - def arbitrary(self, api, path): - def retr(self, *args, **kwargs): - if 'name' not in kwargs.keys(): - raise TrapError(message="no such command") - dummy_test_string = '/interface/bridge add name=unit_test_brige_arbitrary' - result = "/%s/%s add name=%s" % (path[0], path[1], kwargs['name']) - return [result] - return retr - - def add(self, name): - if name == "unit_test_brige_exist": - raise TrapError - return '*A1' - - def remove(self, id): - if id != "*A1": - raise TrapError(message="no such item (4)") - return '*A1' - - def update(self, **kwargs): - if kwargs['.id'] != "*A1" or 'name' not in kwargs.keys(): - raise TrapError(message="no such item (4)") - return ["updated: {'.id': '%s' % kwargs['.id'], 'name': '%s' % kwargs['name']}"] - - def select(self, *args): - dummy_bridge = [{".id": "*A1", "name": "dummy_bridge_A1"}, - {".id": "*A2", "name": "dummy_bridge_A2"}, - {".id": "*A3", "name": "dummy_bridge_A3"}] - - result = [] - for dummy in dummy_bridge: - found = {} - for search in args: - if search in dummy.keys(): - found[search] = dummy[search] - else: - continue - if len(found.keys()) == 2: - result.append(found) - - if result: - return result - else: - return ["no results for 'interface bridge 'query' %s" % ' '.join(args)] - - def select_where(self, api, path): - api_path = Where() - return api_path - - -class Where(object): - def __init__(self): - pass - - def select(self, *args): - return self - - def where(self, *args): - return ["*A1"] - - -class Key(object): - def __init__(self, name): - self.name = name - self.str_return() - - def str_return(self): - return str(self.name) - - class TestRouterosApiModule(ModuleTestCase): def setUp(self): @@ -130,12 +34,17 @@ class TestRouterosApiModule(ModuleTestCase): self.module = api self.module.LibRouterosError = FakeLibRouterosError self.module.connect = MagicMock(new=fake_ros_api) + self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api.create_api', MagicMock(new=fake_ros_api)) + self.patch_create_api.start() self.module.Key = MagicMock(new=Key) self.config_module_args = {"username": "admin", "password": "pаss", "hostname": "127.0.0.1", "path": "interface bridge"} + def tearDown(self): + self.patch_create_api.stop() + def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: set_module_args({}) diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py new file mode 100644 index 0000000..8c3eeac --- /dev/null +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -0,0 +1,766 @@ +# 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 + +import json +import pytest + +from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api +from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase +from ansible_collections.community.routeros.plugins.modules import api_facts + + +API_RESPONSES = { + ('interface', ): [ + { + '.id': '*1', + 'name': 'first-ether', + 'default-name': 'ether1', + 'type': 'ether', + 'mtu': 1500, + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'max-l2mtu': 4074, + 'mac-address': '00:11:22:33:44:55', + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': True, + 'disabled': False, + }, + { + '.id': '*2', + 'name': 'second-ether', + 'default-name': 'ether2', + 'type': 'ether', + 'mtu': 1500, + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'max-l2mtu': 4074, + 'mac-address': '00:11:22:33:44:66', + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': True, + 'slave': True, + 'disabled': False, + }, + { + '.id': '*3', + 'name': 'third-ether', + 'default-name': 'ether3', + 'type': 'ether', + 'mtu': 1500, + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'max-l2mtu': 4074, + 'mac-address': '00:11:22:33:44:77', + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': True, + 'slave': True, + 'disabled': False, + }, + { + '.id': '*4', + 'name': 'fourth-ether', + 'default-name': 'ether4', + 'type': 'ether', + 'mtu': 1500, + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'max-l2mtu': 4074, + 'mac-address': '00:11:22:33:44:88', + 'last-link-down-time': 'apr/23/2022 08:22:50', + 'last-link-up-time': 'apr/23/2022 08:22:52', + 'link-downs': 2, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': True, + 'disabled': False, + }, + { + '.id': '*5', + 'name': 'fifth-ether', + 'default-name': 'ether5', + 'type': 'ether', + 'mtu': 1500, + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'max-l2mtu': 4074, + 'mac-address': '00:11:22:33:44:99', + 'last-link-down-time': 'may/02/2022 18:12:32', + 'last-link-up-time': 'may/02/2022 18:08:01', + 'link-downs': 14, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': False, + 'slave': True, + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'my-bridge', + 'type': 'bridge', + 'mtu': 'auto', + 'actual-mtu': 1500, + 'l2mtu': 1598, + 'mac-address': '00:11:22:33:44:66', + 'last-link-up-time': 'apr/22/2022 07:54:48', + 'link-downs': 0, + 'rx-byte': 1234, + 'tx-byte': 1234, + 'rx-packet': 1234, + 'tx-packet': 1234, + 'rx-drop': 1234, + 'tx-drop': 1234, + 'tx-queue-drop': 1234, + 'rx-error': 1234, + 'tx-error': 1234, + 'fp-rx-byte': 1234, + 'fp-tx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-packet': 1234, + 'running': True, + 'disabled': False, + }, + ], + ('ip', 'address', ): [ + { + '.id': '*1', + 'address': '192.168.1.1/24', + 'network': '192.168.1.0', + 'interface': 'my-bridge', + 'actual-interface': 'my-bridge', + 'invalid': False, + 'dynamic': False, + 'disabled': False, + 'comment': 'Wohnung', + }, + { + '.id': '*5', + 'address': '192.168.2.1/24', + 'network': '192.168.2.0', + 'interface': 'fourth-ether', + 'actual-interface': 'fourth-ether', + 'invalid': False, + 'dynamic': False, + 'disabled': False, + 'comment': 'VoIP', + }, + { + '.id': '*6', + 'address': '1.2.3.4/21', + 'network': '84.73.216.0', + 'interface': 'first-ether', + 'actual-interface': 'first-ether', + 'invalid': False, + 'dynamic': True, + 'disabled': False, + }, + ], + ('ipv6', 'address', ): [ + { + '.id': '*1', + 'address': 'fe80::1:2:3/64', + 'from-pool': '', + 'interface': 'my-bridge', + 'actual-interface': 'my-bridge', + 'eui-64': False, + 'advertise': False, + 'no-dad': False, + 'invalid': False, + 'dynamic': True, + 'link-local': True, + 'disabled': False, + }, + { + '.id': '*2', + 'address': 'fe80::1:2:4/64', + 'from-pool': '', + 'interface': 'fourth-ether', + 'actual-interface': 'fourth-ether', + 'eui-64': False, + 'advertise': False, + 'no-dad': False, + 'invalid': False, + 'dynamic': True, + 'link-local': True, + 'disabled': False, + }, + { + '.id': '*3', + 'address': 'fe80::1:2:5/64', + 'from-pool': '', + 'interface': 'first-ether', + 'actual-interface': 'first-ether', + 'eui-64': False, + 'advertise': False, + 'no-dad': False, + 'invalid': False, + 'dynamic': True, + 'link-local': True, + 'disabled': False, + }, + ], + ('ip', 'neighbor', ): [], + ('system', 'identity', ): [ + { + 'name': 'MikroTik', + }, + ], + ('system', 'resource', ): [ + { + 'uptime': '2w3d4h5m6s', + 'version': '6.49.6 (stable)', + 'build-time': 'Apr/07/2022 17:53:31', + 'free-memory': 12345678, + 'total-memory': 23456789, + 'cpu': 'MIPS 24Kc V7.4', + 'cpu-count': 1, + 'cpu-frequency': 400, + 'cpu-load': 48, + 'free-hdd-space': 123456789, + 'total-hdd-space': 234567890, + 'write-sect-since-reboot': 1234, + 'write-sect-total': 12345, + 'bad-blocks': 0, + 'architecture-name': 'mipsbe', + 'board-name': 'RB750GL', + 'platform': 'MikroTik', + }, + ], + ('system', 'routerboard', ): [ + { + 'routerboard': True, + 'model': '750GL', + 'serial-number': '0123456789AB', + 'firmware-type': 'ar7240', + 'factory-firmware': '3.09', + 'current-firmware': '6.49.6', + 'upgrade-firmware': '6.49.6', + }, + ], + ('routing', 'bgp', 'peer', ): [], + ('routing', 'bgp', 'vpnv4-route', ): [], + ('routing', 'bgp', 'instance', ): [ + { + '.id': '*0', + 'name': 'default', + 'as': 65530, + 'router-id': '0.0.0.0', + 'redistribute-connected': False, + 'redistribute-static': False, + 'redistribute-rip': False, + 'redistribute-ospf': False, + 'redistribute-other-bgp': False, + 'out-filter': '', + 'client-to-client-reflection': True, + 'ignore-as-path-len': False, + 'routing-table': '', + 'default': True, + 'disabled': False, + }, + ], + ('ip', 'route', ): [ + { + '.id': '*30000001', + 'dst-address': '0.0.0.0/0', + 'gateway': '1.2.3.0', + 'gateway-status': '1.2.3.0 reachable via first-ether', + 'distance': 1, + 'scope': 30, + 'target-scope': 10, + 'vrf-interface': 'first-ether', + 'active': True, + 'dynamic': True, + 'static': True, + 'disabled': False, + }, + { + '.id': '*40162F13', + 'dst-address': '84.73.216.0/21', + 'pref-src': '1.2.3.4', + 'gateway': 'first-ether', + 'gateway-status': 'first-ether reachable', + 'distance': 0, + 'scope': 10, + 'active': True, + 'dynamic': True, + 'connect': True, + 'disabled': False, + }, + { + '.id': '*4016AA23', + 'dst-address': '192.168.2.0/24', + 'pref-src': '192.168.2.1', + 'gateway': 'fourth-ether', + 'gateway-status': 'fourth-ether reachable', + 'distance': 0, + 'scope': 10, + 'active': True, + 'dynamic': True, + 'connect': True, + 'disabled': False, + }, + { + '.id': '*40168E05', + 'dst-address': '192.168.1.0/24', + 'pref-src': '192.168.1.1', + 'gateway': 'my-bridge', + 'gateway-status': 'my-bridge reachable', + 'distance': 0, + 'scope': 10, + 'active': True, + 'dynamic': True, + 'connect': True, + 'disabled': False, + }, + ], + ('routing', 'ospf', 'instance', ): [ + { + '.id': '*0', + 'name': 'default', + 'router-id': '0.0.0.0', + 'distribute-default': 'never', + 'redistribute-connected': False, + 'redistribute-static': False, + 'redistribute-rip': False, + 'redistribute-bgp': False, + 'redistribute-other-ospf': False, + 'metric-default': 1, + 'metric-connected': 20, + 'metric-static': 20, + 'metric-rip': 20, + 'metric-bgp': 'auto', + 'metric-other-ospf': 'auto', + 'in-filter': 'ospf-in', + 'out-filter': 'ospf-out', + 'state': 'down', + 'default': True, + 'disabled': False, + }, + ], + ('routing', 'ospf', 'neighbor', ): [], +} + + +class TestRouterosApiFactsModule(ModuleTestCase): + + def setUp(self): + super(TestRouterosApiFactsModule, self).setUp() + librouteros = pytest.importorskip('librouteros') + self.module = api_facts + self.module.LibRouterosError = FakeLibRouterosError + self.module.connect = MagicMock(new=fake_ros_api) + self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api_facts.create_api', MagicMock(new=fake_ros_api)) + self.patch_create_api.start() + self.patch_query_path = patch('ansible_collections.community.routeros.plugins.modules.api_facts.FactsBase.query_path', self.query_path) + self.patch_query_path.start() + self.module.Key = MagicMock(new=Key) + self.config_module_args = { + 'username': 'admin', + 'password': 'pаss', + 'hostname': '127.0.0.1', + } + + def tearDown(self): + self.patch_query_path.stop() + self.patch_create_api.stop() + + def query_path(self, path): + response = API_RESPONSES.get(tuple(path)) + if response is None: + raise Exception('Unexpected command: %s' % repr(path)) + return response + + def test_module_fail_when_required_args_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + set_module_args({}) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + + def test_module_fail_when_invalid_gather_subset(self): + with self.assertRaises(AnsibleFailJson) as exc: + module_args = self.config_module_args.copy() + module_args['gather_subset'] = ['!foobar'] + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Bad subset: foobar') + + def test_full_run(self): + with self.assertRaises(AnsibleExitJson) as exc: + set_module_args(self.config_module_args.copy()) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['ansible_facts']['ansible_net_all_ipv4_addresses'], [ + '192.168.1.1', + '192.168.2.1', + '1.2.3.4', + ]) + self.assertEqual(result['ansible_facts']['ansible_net_all_ipv6_addresses'], [ + 'fe80::1:2:3', + 'fe80::1:2:4', + 'fe80::1:2:5', + ]) + self.assertEqual(result['ansible_facts']['ansible_net_arch'], 'mipsbe') + self.assertEqual(result['ansible_facts']['ansible_net_bgp_instance'], { + 'default': { + 'as': 65530, + 'client-to-client-reflection': True, + 'default': True, + 'disabled': False, + 'ignore-as-path-len': False, + 'name': 'default', + 'out-filter': '', + 'redistribute-connected': False, + 'redistribute-ospf': False, + 'redistribute-other-bgp': False, + 'redistribute-rip': False, + 'redistribute-static': False, + 'router-id': '0.0.0.0', + 'routing-table': '' + }, + }) + self.assertEqual(result['ansible_facts']['ansible_net_bgp_peer'], {}) + self.assertEqual(result['ansible_facts']['ansible_net_bgp_vpnv4_route'], {}) + self.assertEqual(result['ansible_facts']['ansible_net_cpu_load'], 48) + self.assertEqual(result['ansible_facts']['ansible_net_gather_subset'], [ + 'default', + 'hardware', + 'interfaces', + 'routing', + ]) + self.assertEqual(result['ansible_facts']['ansible_net_hostname'], 'MikroTik') + self.assertEqual(result['ansible_facts']['ansible_net_interfaces'], { + 'my-bridge': { + 'actual-mtu': 1500, + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'ipv4': [ + { + 'address': '192.168.1.1', + 'subnet': 24 + } + ], + 'ipv6': [ + { + 'address': 'fe80::1:2:3', + 'subnet': 64 + } + ], + 'l2mtu': 1598, + 'last-link-up-time': 'apr/22/2022 07:54:48', + 'link-downs': 0, + 'mac-address': '00:11:22:33:44:66', + 'mtu': 'auto', + 'name': 'my-bridge', + 'running': True, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'bridge' + }, + 'first-ether': { + 'actual-mtu': 1500, + 'default-name': 'ether1', + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'ipv4': [ + { + 'address': '1.2.3.4', + 'subnet': 21 + } + ], + 'ipv6': [ + { + 'address': 'fe80::1:2:5', + 'subnet': 64 + } + ], + 'l2mtu': 1598, + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'mac-address': '00:11:22:33:44:55', + 'max-l2mtu': 4074, + 'mtu': 1500, + 'name': 'first-ether', + 'running': True, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'ether' + }, + 'second-ether': { + 'actual-mtu': 1500, + 'default-name': 'ether2', + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'l2mtu': 1598, + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'mac-address': '00:11:22:33:44:66', + 'max-l2mtu': 4074, + 'mtu': 1500, + 'name': 'second-ether', + 'running': True, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'slave': True, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'ether' + }, + 'third-ether': { + 'actual-mtu': 1500, + 'default-name': 'ether3', + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'l2mtu': 1598, + 'last-link-up-time': 'apr/22/2022 07:54:55', + 'link-downs': 0, + 'mac-address': '00:11:22:33:44:77', + 'max-l2mtu': 4074, + 'mtu': 1500, + 'name': 'third-ether', + 'running': True, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'slave': True, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'ether' + }, + 'fourth-ether': { + 'actual-mtu': 1500, + 'default-name': 'ether4', + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'ipv4': [ + { + 'address': '192.168.2.1', + 'subnet': 24 + } + ], + 'ipv6': [ + { + 'address': 'fe80::1:2:4', + 'subnet': 64 + } + ], + 'l2mtu': 1598, + 'last-link-down-time': 'apr/23/2022 08:22:50', + 'last-link-up-time': 'apr/23/2022 08:22:52', + 'link-downs': 2, + 'mac-address': '00:11:22:33:44:88', + 'max-l2mtu': 4074, + 'mtu': 1500, + 'name': 'fourth-ether', + 'running': True, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'ether' + }, + 'fifth-ether': { + 'actual-mtu': 1500, + 'default-name': 'ether5', + 'disabled': False, + 'fp-rx-byte': 1234, + 'fp-rx-packet': 1234, + 'fp-tx-byte': 1234, + 'fp-tx-packet': 1234, + 'l2mtu': 1598, + 'last-link-down-time': 'may/02/2022 18:12:32', + 'last-link-up-time': 'may/02/2022 18:08:01', + 'link-downs': 14, + 'mac-address': '00:11:22:33:44:99', + 'max-l2mtu': 4074, + 'mtu': 1500, + 'name': 'fifth-ether', + 'running': False, + 'rx-byte': 1234, + 'rx-drop': 1234, + 'rx-error': 1234, + 'rx-packet': 1234, + 'slave': True, + 'tx-byte': 1234, + 'tx-drop': 1234, + 'tx-error': 1234, + 'tx-packet': 1234, + 'tx-queue-drop': 1234, + 'type': 'ether' + } + }) + self.assertEqual(result['ansible_facts']['ansible_net_memfree_mb'], 12345678 / 1048576.0) + self.assertEqual(result['ansible_facts']['ansible_net_memtotal_mb'], 23456789 / 1048576.0) + self.assertEqual(result['ansible_facts']['ansible_net_model'], '750GL') + self.assertEqual(result['ansible_facts']['ansible_net_neighbors'], []) + self.assertEqual(result['ansible_facts']['ansible_net_ospf_instance'], { + 'default': { + 'default': True, + 'disabled': False, + 'distribute-default': 'never', + 'in-filter': 'ospf-in', + 'metric-bgp': 'auto', + 'metric-connected': 20, + 'metric-default': 1, + 'metric-other-ospf': 'auto', + 'metric-rip': 20, + 'metric-static': 20, + 'name': 'default', + 'out-filter': 'ospf-out', + 'redistribute-bgp': False, + 'redistribute-connected': False, + 'redistribute-other-ospf': False, + 'redistribute-rip': False, + 'redistribute-static': False, + 'router-id': '0.0.0.0', + 'state': 'down' + } + }) + self.assertEqual(result['ansible_facts']['ansible_net_ospf_neighbor'], {}) + self.assertEqual(result['ansible_facts']['ansible_net_route'], { + 'main': { + 'active': True, + 'connect': True, + 'disabled': False, + 'distance': 0, + 'dst-address': '192.168.1.0/24', + 'dynamic': True, + 'gateway': 'my-bridge', + 'gateway-status': 'my-bridge reachable', + 'pref-src': '192.168.1.1', + 'scope': 10 + } + }) + self.assertEqual(result['ansible_facts']['ansible_net_serialnum'], '0123456789AB') + self.assertEqual(result['ansible_facts']['ansible_net_spacefree_mb'], 123456789 / 1048576.0) + self.assertEqual(result['ansible_facts']['ansible_net_spacetotal_mb'], 234567890 / 1048576.0) + self.assertEqual(result['ansible_facts']['ansible_net_uptime'], '2w3d4h5m6s') + self.assertEqual(result['ansible_facts']['ansible_net_version'], '6.49.6 (stable)') From ea782c1cf2dc75e03ad4fd7bfe0b15a627682cd1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 13 May 2022 13:18:28 +0200 Subject: [PATCH 033/365] Add module defaults group community.routeros.api. (#90) --- changelogs/fragments/90-api-action-group.yml | 2 + docs/docsite/rst/api-guide.rst | 41 ++++++++++++++++++-- meta/runtime.yml | 4 ++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/90-api-action-group.yml diff --git a/changelogs/fragments/90-api-action-group.yml b/changelogs/fragments/90-api-action-group.yml new file mode 100644 index 0000000..23c748a --- /dev/null +++ b/changelogs/fragments/90-api-action-group.yml @@ -0,0 +1,2 @@ +minor_changes: + - "Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89)." diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index 482af9a..bccdcfe 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -3,7 +3,7 @@ How to connect to RouterOS devices with the RouterOS API ======================================================== -You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. +You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. The :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. No special setup is needed; the module needs to be run on a host that can connect to the device's API. The most common case is that the module is run on ``localhost``, either by using ``hosts: localhost`` in the playbook, or by using ``delegate_to: localhost`` for the task. The following example shows how to run the equivalent of ``/ip address print``: @@ -33,9 +33,9 @@ No special setup is needed; the module needs to be run on a host that can connec # ca_path: /path/to/ca-certificate.pem register: print_path - - name: Show IP address of first interface - debug: - msg: "{{ print_path.msg[0].address }}" + - name: Show IP address of first interface + ansible.builtin.debug: + msg: "{{ print_path.msg[0].address }}" This results in the following output: @@ -56,6 +56,39 @@ This results in the following output: Check out the documenation of the :ref:`community.routeros.api module ` for details on the options. +Using the ``community.routeros.api`` module defaults group +---------------------------------------------------------- + +To avoid having to specify common parameters for the :ref:`community.routeros.api module ` and :ref:`community.routeros.api_facts module ` in every task, you can use the ``community.routeros.api`` module defaults group: + +.. code-block:: yaml+jinja + + --- + - name: RouterOS test with API + hosts: localhost + gather_facts: no + module_defaults: + group/community.routeros.api + hostname: 192.168.1.1 + password: admin + username: test1234 + # The following options configure TLS/SSL. + # Depending on your setup, these options need different values: + tls: true + validate_certs: true + validate_cert_hostname: true + # If you are using your own PKI, specify the path to your CA certificate here: + # ca_path: /path/to/ca-certificate.pem + tasks: + - name: Gather facts" + community.routeros.api_facts: + + - name: Get "ip address print" + community.routeros.api: + path: "ip address" + +Here both tasks will use the options set for the module defaults group. + Setting up encryption --------------------- diff --git a/meta/runtime.yml b/meta/runtime.yml index 2ee3c9f..17bc297 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,2 +1,6 @@ --- requires_ansible: '>=2.9.10' +action_groups: + api: + - api + - api_facts From 5f912dad165a516050adf3cb6ddff36962e80ab6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 15 May 2022 22:42:26 +0200 Subject: [PATCH 034/365] Improve unit test performance. (Do not install library we do not use in the tests anyway.) (#92) --- .github/workflows/ansible-test.yml | 7 ------- tests/unit/plugins/modules/fake_api.py | 9 ++++++--- tests/unit/plugins/modules/test_api.py | 2 +- tests/unit/plugins/modules/test_api_facts.py | 2 +- tests/unit/requirements-stable-2.9.txt | 4 ---- tests/unit/requirements.txt | 3 --- 6 files changed, 8 insertions(+), 19 deletions(-) delete mode 100644 tests/unit/requirements-stable-2.9.txt diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 6c1a30a..d423345 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -100,13 +100,6 @@ jobs: with: path: ansible_collections/community/routeros - - name: Overwrite unit test requirements (if applicable) - run: | - if [ -e tests/unit/requirements-${{ matrix.ansible }}.txt ]; then - cp tests/unit/requirements-${{ matrix.ansible }}.txt tests/unit/requirements.txt - fi - working-directory: ./ansible_collections/community/routeros - - name: Set up Python ${{ matrix.ansible }} uses: actions/setup-python@v3 with: diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index 03cb6d2..6b5805b 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -34,7 +34,8 @@ class fake_ros_api(object): def __init__(self, api, path): pass - def path(self, api, path): + @classmethod + def path(cls, api, path): fake_bridge = [{".id": "*DC", "name": "b2", "mtu": "auto", "actual-mtu": 1500, "l2mtu": 65535, "arp": "enabled", "arp-timeout": "auto", "mac-address": "3A:C1:90:D6:E8:44", "protocol-mode": "rstp", @@ -45,7 +46,8 @@ class fake_ros_api(object): "dhcp-snooping": "false", "running": "true", "disabled": "false"}] return fake_bridge - def arbitrary(self, api, path): + @classmethod + def arbitrary(cls, api, path): def retr(self, *args, **kwargs): if 'name' not in kwargs.keys(): raise TrapError(message="no such command") @@ -90,7 +92,8 @@ class fake_ros_api(object): else: return ["no results for 'interface bridge 'query' %s" % ' '.join(args)] - def select_where(self, api, path): + @classmethod + def select_where(cls, api, path): api_path = Where() return api_path diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index 98dcd8c..f3dd114 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -30,10 +30,10 @@ class TestRouterosApiModule(ModuleTestCase): def setUp(self): super(TestRouterosApiModule, self).setUp() - librouteros = pytest.importorskip("librouteros") self.module = api self.module.LibRouterosError = FakeLibRouterosError self.module.connect = MagicMock(new=fake_ros_api) + self.module.check_has_library = MagicMock() self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api.create_api', MagicMock(new=fake_ros_api)) self.patch_create_api.start() self.module.Key = MagicMock(new=Key) diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py index 8c3eeac..0c41806 100644 --- a/tests/unit/plugins/modules/test_api_facts.py +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -424,10 +424,10 @@ class TestRouterosApiFactsModule(ModuleTestCase): def setUp(self): super(TestRouterosApiFactsModule, self).setUp() - librouteros = pytest.importorskip('librouteros') self.module = api_facts self.module.LibRouterosError = FakeLibRouterosError self.module.connect = MagicMock(new=fake_ros_api) + self.module.check_has_library = MagicMock() self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api_facts.create_api', MagicMock(new=fake_ros_api)) self.patch_create_api.start() self.patch_query_path = patch('ansible_collections.community.routeros.plugins.modules.api_facts.FactsBase.query_path', self.query_path) diff --git a/tests/unit/requirements-stable-2.9.txt b/tests/unit/requirements-stable-2.9.txt deleted file mode 100644 index 1aa8523..0000000 --- a/tests/unit/requirements-stable-2.9.txt +++ /dev/null @@ -1,4 +0,0 @@ -unittest2 ; python_version <= '2.6' - -# requirements for api module -librouteros < 3.2.0 ; python_version >= '3.6' diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index eac8a96..f4f7b56 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -1,4 +1 @@ unittest2 ; python_version <= '2.6' - -# requirements for api module -librouteros ; python_version >= '3.6' From 109e53497698a05542e30fe411bfebc53f7a719f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 22 May 2022 17:14:53 +0200 Subject: [PATCH 035/365] ansible-core's devel version supports Python 3.11. (#94) --- .github/workflows/ansible-test.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index d423345..65223cc 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -140,12 +140,12 @@ jobs: fail-fast: false matrix: ansible: - - stable-2.13 - devel python: - 3.8 - 3.9 - "3.10" + - "3.11" include: # 2.9 - ansible: stable-2.9 @@ -165,6 +165,11 @@ jobs: python: 3.8 - ansible: stable-2.12 python: "3.10" + # 2.13 + - ansible: stable-2.13 + python: 3.8 + - ansible: stable-2.13 + python: "3.10" steps: - name: Check out code From d57de117f5d71ee7dbfdd59926ddc41cab02594f Mon Sep 17 00:00:00 2001 From: Nikolay Dachev Date: Mon, 23 May 2022 14:44:02 +0300 Subject: [PATCH 036/365] update community.routeros.api query functionality (#63) * update query to accept multiple librouteros ADN parameters * update query for new yml strucutre * add extended_query as separate function:(code in progress) * extended_query main code is ready for review * add changelog #63 * small fix for code indentation * fix pep * clear all pep issues * extended_query ready for review (new yml structure) * small doc fix for std query * Update changelogs/fragments/63-add-extended_query.yml Co-authored-by: Felix Fontein * Update changelogs/fragments/63-add-extended_query.yml Co-authored-by: Felix Fontein * Update argument spec. * Other suggestions. * Fix syntax errors ('is' and 'or' are keywords). * Make everything work again. * Add docs, simplify code. * Add some first tests. * Do not add fake message when there is no search result. * Improve tests. * Fix tests. * update extened query docs and ros api module examples * fix pep plugins/modules/api.py:154:1: W293: blank line contains whitespace * fix extended query example intend * Update plugins/modules/api.py Co-authored-by: Felix Fontein * Update plugins/modules/api.py Co-authored-by: Felix Fontein * fix example docs Co-authored-by: dako Co-authored-by: Felix Fontein --- .../fragments/63-add-extended_query.yml | 3 + plugins/modules/api.py | 416 +++++++++++------- tests/unit/plugins/modules/fake_api.py | 13 +- tests/unit/plugins/modules/test_api.py | 125 +++++- 4 files changed, 405 insertions(+), 152 deletions(-) create mode 100644 changelogs/fragments/63-add-extended_query.yml diff --git a/changelogs/fragments/63-add-extended_query.yml b/changelogs/fragments/63-add-extended_query.yml new file mode 100644 index 0000000..dc39caf --- /dev/null +++ b/changelogs/fragments/63-add-extended_query.yml @@ -0,0 +1,3 @@ +minor_changes: + - "api - add new option ``extended query`` more complex queries against RouterOS API (https://github.com/ansible-collections/community.routeros/pull/63)." + - "api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63)." diff --git a/plugins/modules/api.py b/plugins/modules/api.py index dc58ca5..85dc704 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -52,7 +52,7 @@ options: description: - Query given path for selected query attributes from RouterOS aip. - WHERE is key word which extend query. WHERE format is key operator value - with spaces. - - WHERE valid operators are C(==), C(!=), C(>), C(<). + - WHERE valid operators are C(==) or C(eq), C(!=) or C(not), C(>) or C(more), C(<) or C(less). - Example path C(ip address) and query C(.id address) will return only C(.id) and C(address) for all items in C(ip address) path. - Example path C(ip address) and query C(.id address WHERE address == 1.1.1.3/32). will return only C(.id) and C(address) for items in C(ip address) path, where address is eq to 1.1.1.3/32. @@ -60,6 +60,69 @@ options: return only interfaces C(mtu,name) where mtu is bigger than 1400. - Equivalent in RouterOS CLI C(/interface print where mtu > 1400). type: str + extended_query: + description: + - Extended query given path for selected query attributes from RouterOS API. + - Extended query allow conjunctive input. If there is no matching entry, an empty list will be returned. + type: dict + suboptions: + attributes: + description: + - The list of attributes to return. + - Every attribute used in a I(where) clause need to be listed here. + type: list + elements: str + required: true + where: + description: + - Allows to restrict the objects returned. + - The conditions here must all match. An I(or) condition needs at least one of its conditions to match. + type: list + elements: dict + suboptions: + attribute: + description: + - The attribute to match. Must be part of I(attributes). + - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + type: str + is: + description: + - The operator to use for matching. + - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more). + - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list. + - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + type: str + choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"] + value: + description: + - The value to compare to. Must be a list for I(is=in). + - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + type: raw + or: + description: + - A list of conditions so that at least one of them has to match. + - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + type: list + elements: dict + suboptions: + attribute: + description: + - The attribute to match. Must be part of I(attributes). + type: str + required: true + is: + description: + - The operator to use for matching. + - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more). + - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list. + type: str + choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"] + required: true + value: + description: + - The value to compare to. Must be a list for I(is=in). + type: raw + required: true cmd: description: - Execute any/arbitrary command in selected path, after the command we can add C(.id). @@ -72,132 +135,103 @@ seealso: ''' EXAMPLES = ''' ---- -- name: Use RouterOS API - hosts: localhost - gather_facts: no - vars: - hostname: "ros_api_hostname/ip" - username: "admin" - password: "secret_password" - +- name: Get example - ip address print + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" path: "ip address" + register: ipaddrd_printout - nic: "ether2" - ip1: "1.1.1.1/32" - ip2: "2.2.2.2/32" - ip3: "3.3.3.3/32" +- name: Dump "Get example" output + ansible.builtin.debug: + msg: '{{ ipaddrd_printout }}' - tasks: - - name: Get "{{ path }} print" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - register: print_path +- name: Add example - ip address + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "ip address" + add: "address=192.168.255.10/24 interface=ether2" - - name: Dump "{{ path }} print" output - ansible.builtin.debug: - msg: '{{ print_path }}' +- name: Query example - ".id, address" in "ip address WHERE address == 192.168.255.10/24" + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "ip address" + query: ".id address WHERE address == {{ ip2 }}" + register: queryout - - name: Add ip address "{{ ip1 }}" and "{{ ip2 }}" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - add: "{{ item }}" - loop: - - "address={{ ip1 }} interface={{ nic }}" - - "address={{ ip2 }} interface={{ nic }}" - register: addout +- name: Dump "Query example" output + ansible.builtin.debug: + msg: '{{ queryout }}' - - name: Dump "Add ip address" output - ".id" for new added items - ansible.builtin.debug: - msg: '{{ addout }}' +- name: Extended query example - ".id,address,network" where address is not 192.168.255.10/24 or is 10.20.36.20/24 + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "ip address" + extended_query: + attributes: + - network + - address + - .id + where: + - attribute: "network" + is: "==" + value: "192.168.255.0" + - or: + - attribute: "address" + is: "!=" + value: "192.168.255.10/24" + - attribute: "address" + is: "eq" + value: "10.20.36.20/24" + - attribute: "network" + is: "in" + value: + - "10.20.36.0" + - "192.168.255.0" + register: extended_queryout - - name: Query for ".id" in "{{ path }} WHERE address == {{ ip2 }}" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - query: ".id address WHERE address == {{ ip2 }}" - register: queryout +- name: Dump "Extended query example" output + ansible.builtin.debug: + msg: '{{ extended_queryout }}' - - name: Dump "Query for" output and set fact with ".id" for "{{ ip2 }}" - ansible.builtin.debug: - msg: '{{ queryout }}' +- name: Update example - ether2 ip addres with ".id = *14" + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "ip address" + update: >- + .id=*14 + address=192.168.255.20/24 + comment={{ 'Update 192.168.255.10/24 to 192.168.255.20/24 on ether2' | community.routeros.quote_argument_value }} - - name: Store query_id for later usage - ansible.builtin.set_fact: - query_id: "{{ queryout['msg'][0]['.id'] }}" +- name: Remove example - ether2 ip 192.168.255.20/24 with ".id = *14" + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "ip address" + remove: "*14" - - name: Update ".id = {{ query_id }}" taken with custom fact "fquery_id" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - update: >- - .id={{ query_id }} - address={{ ip3 }} - comment={{ 'A comment with spaces' | community.routeros.quote_argument_value }} - register: updateout +- name: Arbitrary command example "/system identity print" + community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: "system identity" + cmd: "print" + register: arbitraryout - - name: Dump "Update" output - ansible.builtin.debug: - msg: '{{ updateout }}' - - - name: Remove ips - stage 1 - query ".id" for "{{ ip2 }}" and "{{ ip3 }}" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - query: ".id address WHERE address == {{ item }}" - register: id_to_remove - loop: - - "{{ ip2 }}" - - "{{ ip3 }}" - - - name: Set fact for ".id" from "Remove ips - stage 1 - query" - ansible.builtin.set_fact: - to_be_remove: "{{ to_be_remove |default([]) + [item['msg'][0]['.id']] }}" - loop: "{{ id_to_remove.results }}" - - - name: Dump "Remove ips - stage 1 - query" output - ansible.builtin.debug: - msg: '{{ to_be_remove }}' - - # Remove "{{ rmips }}" with ".id" by "to_be_remove" from query - - name: Remove ips - stage 2 - remove "{{ ip2 }}" and "{{ ip3 }}" by '.id' - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "{{ path }}" - remove: "{{ item }}" - register: remove - loop: "{{ to_be_remove }}" - - - name: Dump "Remove ips - stage 2 - remove" output - ansible.builtin.debug: - msg: '{{ remove }}' - - - name: Arbitrary command example "/system identity print" - community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "system identity" - cmd: "print" - register: cmdout - - - name: Dump "Arbitrary command example" output - ansible.builtin.debug: - msg: "{{ cmdout }}" +- name: Dump "Arbitrary command example" output + ansible.builtin.debug: + msg: '{{ arbitraryout }}' ''' RETURN = ''' @@ -232,7 +266,7 @@ import traceback try: from librouteros.exceptions import LibRouterosError - from librouteros.query import Key + from librouteros.query import Key, Or except Exception: # Handled in api module_utils pass @@ -247,13 +281,33 @@ class ROS_api_module: update=dict(type='str'), cmd=dict(type='str'), query=dict(type='str'), + extended_query=dict(type='dict', options=dict( + attributes=dict(type='list', elements='str', required=True), + where=dict( + type='list', + elements='dict', + options={ + 'attribute': dict(type='str'), + 'is': dict(type='str', choices=["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]), + 'value': dict(type='raw'), + 'or': dict(type='list', elements='dict', options={ + 'attribute': dict(type='str', required=True), + 'is': dict(type='str', choices=["==", "!=", ">", "<", "in", "eq", "not", "more", "less"], required=True), + 'value': dict(type='raw', required=True), + }), + }, + required_together=[('attribute', 'is', 'value')], + mutually_exclusive=[('attribute', 'or')], + required_one_of=[('attribute', 'or')], + ), + )), ) module_args.update(api_argument_spec()) self.module = AnsibleModule(argument_spec=module_args, supports_check_mode=False, mutually_exclusive=(('add', 'remove', 'update', - 'cmd', 'query'),),) + 'cmd', 'query', 'extended_query'),),) check_has_library(self.module) @@ -267,32 +321,7 @@ class ROS_api_module: self.where = None self.query = self.module.params['query'] - if self.query: - where_index = self.query.find(' WHERE ') - if where_index < 0: - self.query = self.split_params(self.query) - else: - where = self.query[where_index + len(' WHERE '):] - self.query = self.split_params(self.query[:where_index]) - # where must be of the format ' ' - m = re.match(r'^\s*([^ ]+)\s+([^ ]+)\s+(.*)$', where) - if not m: - self.errors("invalid syntax for 'WHERE %s'" % where) - try: - self.where = [ - m.group(1), # attribute - m.group(2), # operator - parse_argument_value(m.group(3).rstrip())[0], # value - ] - except ParseError as exc: - self.errors("invalid syntax for 'WHERE %s': %s" % (where, exc)) - try: - idx = self.query.index('WHERE') - self.where = self.query[idx + 1:] - self.query = self.query[:idx] - except ValueError: - # Raised when WHERE has not been found - pass + self.extended_query = self.module.params['extended_query'] self.result = dict( message=[]) @@ -308,12 +337,58 @@ class ROS_api_module: elif self.update: self.api_update() elif self.query: + self.check_query() self.api_query() + elif self.extended_query: + self.check_extended_query() + self.api_extended_query() elif self.arbitrary: self.api_arbitrary() else: self.api_get_all() + def check_query(self): + where_index = self.query.find(' WHERE ') + if where_index < 0: + self.query = self.split_params(self.query) + else: + where = self.query[where_index + len(' WHERE '):] + self.query = self.split_params(self.query[:where_index]) + # where must be of the format ' ' + m = re.match(r'^\s*([^ ]+)\s+([^ ]+)\s+(.*)$', where) + if not m: + self.errors("invalid syntax for 'WHERE %s'" % where) + try: + self.where = [ + m.group(1), # attribute + m.group(2), # operator + parse_argument_value(m.group(3).rstrip())[0], # value + ] + except ParseError as exc: + self.errors("invalid syntax for 'WHERE %s': %s" % (where, exc)) + try: + idx = self.query.index('WHERE') + self.where = self.query[idx + 1:] + self.query = self.query[:idx] + except ValueError: + # Raised when WHERE has not been found + pass + + def check_extended_query_syntax(self, test_atr, or_msg=''): + if test_atr['is'] == "in" and not isinstance(test_atr['value'], list): + self.errors("invalid syntax 'extended_query':'where':%s%s 'value' must be a type list" % (or_msg, test_atr)) + + def check_extended_query(self): + if self.extended_query["where"]: + for i in self.extended_query['where']: + if i["or"] is not None: + if len(i['or']) < 2: + self.errors("invalid syntax 'extended_query':'where':'or':%s 'or' requires minimum two items" % i["or"]) + for orv in i['or']: + self.check_extended_query_syntax(orv, ":'or':") + else: + self.check_extended_query_syntax(i) + def list_to_dic(self, ldict): return convert_list_to_dictionary(ldict, skip_empty_values=True, require_assignment=True) @@ -370,18 +445,18 @@ class ROS_api_module: def api_query(self): keys = {} for k in self.query: - if k == 'id': + if 'id' in k and k != ".id": self.errors("'%s' must be '.id'" % k) keys[k] = Key(k) try: if self.where: - if self.where[1] == '==': + if self.where[1] in ('==', 'eq'): select = self.api_path.select(*keys).where(keys[self.where[0]] == self.where[2]) - elif self.where[1] == '!=': + elif self.where[1] in ('!=', 'not'): select = self.api_path.select(*keys).where(keys[self.where[0]] != self.where[2]) - elif self.where[1] == '>': + elif self.where[1] in ('>', 'more'): select = self.api_path.select(*keys).where(keys[self.where[0]] > self.where[2]) - elif self.where[1] == '<': + elif self.where[1] in ('<', 'less'): select = self.api_path.select(*keys).where(keys[self.where[0]] < self.where[2]) else: self.errors("'%s' is not operator for 'where'" @@ -400,6 +475,49 @@ class ROS_api_module: except LibRouterosError as e: self.errors(e) + def build_api_extended_query(self, item): + if item['attribute'] not in self.extended_query['attributes']: + self.errors("'%s' attribute is not in attributes: %s" + % (item, self.extended_query['attributes'])) + if item['is'] in ('eq', '=='): + return self.query_keys[item['attribute']] == item['value'] + elif item['is'] in ('not', '!='): + return self.query_keys[item['attribute']] != item['value'] + elif item['is'] in ('less', '<'): + return self.query_keys[item['attribute']] < item['value'] + elif item['is'] in ('more', '>'): + return self.query_keys[item['attribute']] > item['value'] + elif item['is'] == 'in': + return self.query_keys[item['attribute']].In(*item['value']) + else: + self.errors("'%s' is not operator for 'is'" % item['is']) + + def api_extended_query(self): + self.query_keys = {} + for k in self.extended_query['attributes']: + if k == 'id': + self.errors("'extended_query':'attributes':'%s' must be '.id'" % k) + self.query_keys[k] = Key(k) + try: + if self.extended_query['where']: + where_args = [] + for i in self.extended_query['where']: + if i['or']: + where_or_args = [] + for ior in i['or']: + where_or_args.append(self.build_api_extended_query(ior)) + where_args.append(Or(*where_or_args)) + else: + where_args.append(self.build_api_extended_query(i)) + select = self.api_path.select(*self.query_keys).where(*where_args) + else: + select = self.api_path.select(*self.extended_query['attributes']) + for row in select: + self.result['message'].append(row) + self.return_result(False) + except LibRouterosError as e: + self.errors(e) + def api_arbitrary(self): param = {} self.arbitrary = self.split_params(self.arbitrary) diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index 6b5805b..cef6586 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -90,7 +90,7 @@ class fake_ros_api(object): if result: return result else: - return ["no results for 'interface bridge 'query' %s" % ' '.join(args)] + return [] @classmethod def select_where(cls, api, path): @@ -106,7 +106,7 @@ class Where(object): return self def where(self, *args): - return ["*A1"] + return [{".id": "*A1", "name": "dummy_bridge_A1"}] class Key(object): @@ -116,3 +116,12 @@ class Key(object): def str_return(self): return str(self.name) + + +class Or(object): + def __init__(self, *args): + self.args = args + self.str_return() + + def str_return(self): + return repr(self.args) diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index f3dd114..94982ac 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -21,7 +21,7 @@ import json import pytest from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock -from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, Or, fake_ros_api from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api @@ -37,6 +37,7 @@ class TestRouterosApiModule(ModuleTestCase): self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api.create_api', MagicMock(new=fake_ros_api)) self.patch_create_api.start() self.module.Key = MagicMock(new=Key) + self.module.Or = MagicMock(new=Or) self.config_module_args = {"username": "admin", "password": "pаss", "hostname": "127.0.0.1", @@ -164,6 +165,11 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + {'.id': '*A2', 'name': 'dummy_bridge_A2'}, + {'.id': '*A3', 'name': 'dummy_bridge_A3'}, + ]) @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api) def test_api_query_missing_key(self): @@ -175,6 +181,7 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], ["no results for 'interface bridge 'query' .id other"]) @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.select_where) def test_api_query_and_WHERE(self): @@ -186,6 +193,9 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + ]) @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.select_where) def test_api_query_and_WHERE_no_cond(self): @@ -197,3 +207,116 @@ class TestRouterosApiModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api) + def test_api_extended_query(self): + with self.assertRaises(AnsibleExitJson) as exc: + module_args = self.config_module_args.copy() + module_args['extended_query'] = { + 'attributes': ['.id', 'name'], + } + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + {'.id': '*A2', 'name': 'dummy_bridge_A2'}, + {'.id': '*A3', 'name': 'dummy_bridge_A3'}, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api) + def test_api_extended_query_missing_key(self): + with self.assertRaises(AnsibleExitJson) as exc: + module_args = self.config_module_args.copy() + module_args['extended_query'] = { + 'attributes': ['.id', 'other'], + } + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], []) + + @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.select_where) + def test_api_extended_query_and_WHERE(self): + with self.assertRaises(AnsibleExitJson) as exc: + module_args = self.config_module_args.copy() + module_args['extended_query'] = { + 'attributes': ['.id', 'name'], + 'where': [ + { + 'attribute': 'name', + 'is': '==', + 'value': 'dummy_bridge_A2', + }, + ], + } + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.select_where) + def test_api_extended_query_and_WHERE_no_cond(self): + with self.assertRaises(AnsibleExitJson) as exc: + module_args = self.config_module_args.copy() + module_args['extended_query'] = { + 'attributes': ['.id', 'name'], + 'where': [ + { + 'attribute': 'name', + 'is': 'not', + 'value': 'dummy_bridge_A2', + }, + ], + } + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.select_where) + def test_api_extended_query_and_WHERE_or(self): + with self.assertRaises(AnsibleExitJson) as exc: + module_args = self.config_module_args.copy() + module_args['extended_query'] = { + 'attributes': ['.id', 'name'], + 'where': [ + { + 'or': [ + { + 'attribute': 'name', + 'is': 'in', + 'value': [1, 2], + }, + { + 'attribute': 'name', + 'is': '!=', + 'value': 5, + }, + ], + }, + ], + } + set_module_args(module_args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['msg'], [ + {'.id': '*A1', 'name': 'dummy_bridge_A1'}, + ]) From ff66ba9289f80322fb2d192dcfe05a94bc229d40 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 24 May 2022 18:23:44 +0200 Subject: [PATCH 037/365] Add api_find_and_modify module. (#93) --- meta/runtime.yml | 1 + plugins/module_utils/_api_data.py | 1798 +++++++++++++++++ plugins/modules/api_find_and_modify.py | 312 +++ .../plugins/module_utils/test__api_data.py | 91 + tests/unit/plugins/modules/fake_api.py | 109 + .../modules/test_api_find_and_modify.py | 666 ++++++ tests/unit/requirements.txt | 1 + 7 files changed, 2978 insertions(+) create mode 100644 plugins/module_utils/_api_data.py create mode 100644 plugins/modules/api_find_and_modify.py create mode 100644 tests/unit/plugins/module_utils/test__api_data.py create mode 100644 tests/unit/plugins/modules/test_api_find_and_modify.py diff --git a/meta/runtime.yml b/meta/runtime.yml index 17bc297..6a8be34 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -4,3 +4,4 @@ action_groups: api: - api - api_facts + - api_find_and_modify diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py new file mode 100644 index 0000000..ab771d0 --- /dev/null +++ b/plugins/module_utils/_api_data.py @@ -0,0 +1,1798 @@ +# -*- coding: utf-8 -*- +# Copyright: (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# The data inside here is private to this collection. If you use this from outside the collection, +# you are on your own. There can be random changes to its format even in bugfix releases! + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class APIData(object): + def __init__(self, primary_keys=None, + stratify_keys=None, + has_identifier=False, + single_value=False, + unknown_mechanism=False, + fully_understood=False, + fixed_entries=False, + fields=None): + if sum([primary_keys is not None, stratify_keys is not None, has_identifier, single_value, unknown_mechanism]) > 1: + raise ValueError('primary_keys, stratify_keys, has_identifier, single_value, and unknown_mechanism are mutually exclusive') + if unknown_mechanism and fully_understood: + raise ValueError('unknown_mechanism and fully_understood cannot be combined') + self.primary_keys = primary_keys + self.stratify_keys = stratify_keys + self.has_identifier = has_identifier + self.single_value = single_value + self.unknown_mechanism = unknown_mechanism + self.fully_understood = fully_understood + self.fixed_entries = fixed_entries + if fixed_entries and primary_keys is None: + raise ValueError('fixed_entries can only be used with primary_keys') + if fields is None: + raise ValueError('fields must be provided') + self.fields = fields + if primary_keys: + for pk in primary_keys: + if pk not in fields: + raise ValueError('Primary key {pk} must be in fields!'.format(pk=pk)) + if stratify_keys: + for sk in stratify_keys: + if sk not in fields: + raise ValueError('Stratify key {sk} must be in fields!'.format(sk=sk)) + + +class KeyInfo(object): + def __init__(self, _dummy=None, can_disable=False, remove_value=None, default=None, required=False, automatically_computed_from=None): + if _dummy is not None: + raise ValueError('KeyInfo() does not have positional arguments') + if sum([required, default is not None, automatically_computed_from is not None, can_disable]) > 1: + raise ValueError('required, default, automatically_computed_from, and can_disable are mutually exclusive') + if not can_disable and remove_value is not None: + raise ValueError('remove_value can only be specified if can_disable=True') + self.can_disable = can_disable + self.remove_value = remove_value + self.automatically_computed_from = automatically_computed_from + self.default = default + self.required = required + + +def split_path(path): + parts = path.split() + if len(parts) == 1 and parts[0] == '': + parts = [] + return parts + + +def join_path(path): + return ' '.join(path) + + +# How to obtain this information: +# 1. Run `/export verbose` in the CLI; +# 2. All attributes listed there go into the `fields` list; +# attributes which can have a `!` ahead should have `canDisable=True` +# 3. All bold attributes go into the `primary_keys` list -- this is not always true! + +PATHS = { + ('interface', 'bridge'): APIData( + # fully_understood=True, + primary_keys=('name', ), + fields={ + 'admin-mac': KeyInfo(), + 'ageing-time': KeyInfo(default='5m'), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'auto-mac': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-snooping': KeyInfo(default=False), + 'disabled': KeyInfo(default=False), + 'fast-forward': KeyInfo(default=True), + 'forward-delay': KeyInfo(default='15s'), + 'igmp-snooping': KeyInfo(default=False), + 'max-message-age': KeyInfo(default='20s'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'priority': KeyInfo(default='0x8000'), + 'protocol-mode': KeyInfo(default='rstp'), + 'transmit-hold-count': KeyInfo(default=6), + 'vlan-filtering': KeyInfo(default=False), + }, + ), + ('interface', 'ethernet'): APIData( + fixed_entries=True, + fully_understood=True, + primary_keys=('default-name', ), + fields={ + 'default-name': KeyInfo(), + 'advertise': KeyInfo(), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'auto-negotiation': KeyInfo(default=True), + 'bandwidth': KeyInfo(default='unlimited/unlimited'), + 'disabled': KeyInfo(default=False), + 'full-duplex': KeyInfo(default=True), + 'l2mtu': KeyInfo(default=1598), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mac-address': KeyInfo(), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'orig-mac-address': KeyInfo(), + 'rx-flow-control': KeyInfo(default='off'), + 'sfp-rate-select': KeyInfo(default='high'), + 'sfp-shutdown-temperature': KeyInfo(default='95C'), + 'speed': KeyInfo(), + 'tx-flow-control': KeyInfo(default='off'), + }, + ), + ('interface', 'list'): APIData( + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'exclude': KeyInfo(), + 'include': KeyInfo(), + 'name': KeyInfo(), + }, + ), + ('interface', 'lte', 'apn'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'add-default-route': KeyInfo(), + 'apn': KeyInfo(), + 'default-route-distance': KeyInfo(), + 'name': KeyInfo(), + 'use-peer-dns': KeyInfo(), + }, + ), + ('interface', 'wireless', 'security-profiles'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'authentication-types': KeyInfo(), + 'disable-pmkid': KeyInfo(), + 'eap-methods': KeyInfo(), + 'group-ciphers': KeyInfo(), + 'group-key-update': KeyInfo(), + 'interim-update': KeyInfo(), + 'management-protection': KeyInfo(), + 'management-protection-key': KeyInfo(), + 'mode': KeyInfo(), + 'mschapv2-password': KeyInfo(), + 'mschapv2-username': KeyInfo(), + 'name': KeyInfo(), + 'radius-called-format': KeyInfo(), + 'radius-eap-accounting': KeyInfo(), + 'radius-mac-accounting': KeyInfo(), + 'radius-mac-authentication': KeyInfo(), + 'radius-mac-caching': KeyInfo(), + 'radius-mac-format': KeyInfo(), + 'radius-mac-mode': KeyInfo(), + 'static-algo-0': KeyInfo(), + 'static-algo-1': KeyInfo(), + 'static-algo-2': KeyInfo(), + 'static-algo-3': KeyInfo(), + 'static-key-0': KeyInfo(), + 'static-key-1': KeyInfo(), + 'static-key-2': KeyInfo(), + 'static-key-3': KeyInfo(), + 'static-sta-private-algo': KeyInfo(), + 'static-sta-private-key': KeyInfo(), + 'static-transmit-key': KeyInfo(), + 'supplicant-identity': KeyInfo(), + 'tls-certificate': KeyInfo(), + 'tls-mode': KeyInfo(), + 'unicast-ciphers': KeyInfo(), + 'wpa-pre-shared-key': KeyInfo(), + 'wpa2-pre-shared-key': KeyInfo(), + }, + ), + ('ip', 'hotspot', 'profile'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'dns-name': KeyInfo(), + 'hotspot-address': KeyInfo(), + 'html-directory': KeyInfo(), + 'html-directory-override': KeyInfo(), + 'http-cookie-lifetime': KeyInfo(), + 'http-proxy': KeyInfo(), + 'login-by': KeyInfo(), + 'name': KeyInfo(), + 'rate-limit': KeyInfo(), + 'smtp-server': KeyInfo(), + 'split-user-domain': KeyInfo(), + 'use-radius': KeyInfo(), + }, + ), + ('ip', 'hotspot', 'user', 'profile'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'add-mac-cookie': KeyInfo(), + 'address-list': KeyInfo(), + 'idle-timeout': KeyInfo(), + 'insert-queue-before': KeyInfo(can_disable=True), + 'keepalive-timeout': KeyInfo(), + 'mac-cookie-timeout': KeyInfo(), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True), + 'queue-type': KeyInfo(can_disable=True), + 'shared-users': KeyInfo(), + 'status-autorefresh': KeyInfo(), + 'transparent-proxy': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'mode-config'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'name': KeyInfo(), + 'responder': KeyInfo(), + 'use-responder-dns': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'policy', 'group'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'name': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'profile'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'dh-group': KeyInfo(), + 'dpd-interval': KeyInfo(), + 'dpd-maximum-failures': KeyInfo(), + 'enc-algorithm': KeyInfo(), + 'hash-algorithm': KeyInfo(), + 'lifetime': KeyInfo(), + 'name': KeyInfo(), + 'nat-traversal': KeyInfo(), + 'proposal-check': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'proposal'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'auth-algorithms': KeyInfo(), + 'disabled': KeyInfo(), + 'enc-algorithms': KeyInfo(), + 'lifetime': KeyInfo(), + 'name': KeyInfo(), + 'pfs-group': KeyInfo(), + }, + ), + ('ip', 'pool'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'name': KeyInfo(), + 'ranges': KeyInfo(), + }, + ), + ('ip', 'dhcp-server'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(required=True), + 'authoritative': KeyInfo(default=True), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'lease-script': KeyInfo(default=''), + 'lease-time': KeyInfo(default='10m'), + 'name': KeyInfo(), + 'use-radius': KeyInfo(default=False), + }, + ), + ('routing', 'ospf', 'instance'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'distribute-default': KeyInfo(), + 'domain-id': KeyInfo(can_disable=True), + 'domain-tag': KeyInfo(can_disable=True), + 'in-filter': KeyInfo(), + 'metric-bgp': KeyInfo(), + 'metric-connected': KeyInfo(), + 'metric-default': KeyInfo(), + 'metric-other-ospf': KeyInfo(), + 'metric-rip': KeyInfo(), + 'metric-static': KeyInfo(), + 'mpls-te-area': KeyInfo(can_disable=True), + 'mpls-te-router-id': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'out-filter': KeyInfo(), + 'redistribute-bgp': KeyInfo(), + 'redistribute-connected': KeyInfo(), + 'redistribute-other-ospf': KeyInfo(), + 'redistribute-rip': KeyInfo(), + 'redistribute-static': KeyInfo(), + 'router-id': KeyInfo(), + 'routing-table': KeyInfo(can_disable=True), + 'use-dn': KeyInfo(can_disable=True), + }, + ), + ('routing', 'ospf', 'area'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'area-id': KeyInfo(), + 'disabled': KeyInfo(), + 'instance': KeyInfo(), + 'name': KeyInfo(), + 'type': KeyInfo(), + }, + ), + ('routing', 'ospf-v3', 'instance'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'distribute-default': KeyInfo(), + 'metric-bgp': KeyInfo(), + 'metric-connected': KeyInfo(), + 'metric-default': KeyInfo(), + 'metric-other-ospf': KeyInfo(), + 'metric-rip': KeyInfo(), + 'metric-static': KeyInfo(), + 'name': KeyInfo(), + 'redistribute-bgp': KeyInfo(), + 'redistribute-connected': KeyInfo(), + 'redistribute-other-ospf': KeyInfo(), + 'redistribute-rip': KeyInfo(), + 'redistribute-static': KeyInfo(), + 'router-id': KeyInfo(), + }, + ), + ('routing', 'ospf-v3', 'area'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'area-id': KeyInfo(), + 'disabled': KeyInfo(), + 'instance': KeyInfo(), + 'name': KeyInfo(), + 'type': KeyInfo(), + }, + ), + ('snmp', 'community'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'addresses': KeyInfo(), + 'authentication-password': KeyInfo(), + 'authentication-protocol': KeyInfo(), + 'disabled': KeyInfo(), + 'encryption-password': KeyInfo(), + 'encryption-protocol': KeyInfo(), + 'name': KeyInfo(), + 'read-access': KeyInfo(), + 'security': KeyInfo(), + 'write-access': KeyInfo(), + }, + ), + ('caps-man', 'aaa'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'called-format': KeyInfo(default='mac:ssid'), + 'interim-update': KeyInfo(default='disabled'), + 'mac-caching': KeyInfo(default='disabled'), + 'mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), + 'mac-mode': KeyInfo(default='as-username'), + }, + ), + ('caps-man', 'manager', 'interface'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'forbid': KeyInfo(), + 'interface': KeyInfo(), + }, + ), + ('certificate', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'crl-download': KeyInfo(default=False), + 'crl-store': KeyInfo(default='ram'), + 'crl-use': KeyInfo(default=False), + }, + ), + ('interface', 'bridge', 'port'): APIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'auto-isolate': KeyInfo(default=False), + 'bpdu-guard': KeyInfo(default=False), + 'bridge': KeyInfo(required=True), + 'broadcast-flood': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'edge': KeyInfo(default='auto'), + 'fast-leave': KeyInfo(default=False), + 'frame-types': KeyInfo(default='admit-all'), + 'horizon': KeyInfo(default='none'), + 'hw': KeyInfo(default=True), + 'ingress-filtering': KeyInfo(default=False), + 'interface': KeyInfo(), + 'internal-path-cost': KeyInfo(default=10), + 'learn': KeyInfo(default='auto'), + 'multicast-router': KeyInfo(default='temporary-query'), + 'path-cost': KeyInfo(default=10), + 'point-to-point': KeyInfo(default='auto'), + 'priority': KeyInfo(default='0x80'), + 'pvid': KeyInfo(default=1), + 'restricted-role': KeyInfo(default=False), + 'restricted-tcn': KeyInfo(default=False), + 'tag-stacking': KeyInfo(default=False), + 'trusted': KeyInfo(default=False), + 'unknown-multicast-flood': KeyInfo(default=True), + 'unknown-unicast-flood': KeyInfo(default=True), + }, + ), + ('interface', 'bridge', 'port-controller'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'cascade-ports': KeyInfo(default=''), + 'switch': KeyInfo(default='none'), + }, + ), + ('interface', 'bridge', 'port-extender'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'control-ports': KeyInfo(default=''), + 'excluded-ports': KeyInfo(default=''), + 'switch': KeyInfo(default='none'), + }, + ), + ('interface', 'bridge', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'use-ip-firewall': KeyInfo(default=False), + 'use-ip-firewall-for-pppoe': KeyInfo(default=False), + 'use-ip-firewall-for-vlan': KeyInfo(default=False), + }, + ), + ('ip', 'firewall', 'connection', 'tracking'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default='auto'), + 'generic-timeout': KeyInfo(default='10m'), + 'icmp-timeout': KeyInfo(default='10s'), + 'loose-tcp-tracking': KeyInfo(default=True), + 'tcp-close-timeout': KeyInfo(default='10s'), + 'tcp-close-wait-timeout': KeyInfo(default='10s'), + 'tcp-established-timeout': KeyInfo(default='1d'), + 'tcp-fin-wait-timeout': KeyInfo(default='10s'), + 'tcp-last-ack-timeout': KeyInfo(default='10s'), + 'tcp-max-retrans-timeout': KeyInfo(default='5m'), + 'tcp-syn-received-timeout': KeyInfo(default='5s'), + 'tcp-syn-sent-timeout': KeyInfo(default='5s'), + 'tcp-time-wait-timeout': KeyInfo(default='10s'), + 'tcp-unacked-timeout': KeyInfo(default='5m'), + 'udp-stream-timeout': KeyInfo(default='3m'), + 'udp-timeout': KeyInfo(default='10s'), + }, + ), + ('ip', 'neighbor', 'discovery-settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'discover-interface-list': KeyInfo(), + 'lldp-med-net-policy-vlan': KeyInfo(default='disabled'), + 'protocol': KeyInfo(default='cdp,lldp,mndp'), + }, + ), + ('ip', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accept-redirects': KeyInfo(default=False), + 'accept-source-route': KeyInfo(default=False), + 'allow-fast-path': KeyInfo(default=True), + 'arp-timeout': KeyInfo(default='30s'), + 'icmp-rate-limit': KeyInfo(default=10), + 'icmp-rate-mask': KeyInfo(default='0x1818'), + 'ip-forward': KeyInfo(default=True), + 'max-neighbor-entries': KeyInfo(default=8192), + 'route-cache': KeyInfo(default=True), + 'rp-filter': KeyInfo(default=False), + 'secure-redirects': KeyInfo(default=True), + 'send-redirects': KeyInfo(default=True), + 'tcp-syncookies': KeyInfo(default=False), + }, + ), + ('ipv6', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), + 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), + 'forward': KeyInfo(default=True), + 'max-neighbor-entries': KeyInfo(default=8192), + }, + ), + ('interface', 'detect-internet'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'detect-interface-list': KeyInfo(default='none'), + 'internet-interface-list': KeyInfo(default='none'), + 'lan-interface-list': KeyInfo(default='none'), + 'wan-interface-list': KeyInfo(default='none'), + }, + ), + ('interface', 'l2tp-server', 'server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=False), + 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'caller-id-type': KeyInfo(default='ip-address'), + 'default-profile': KeyInfo(default='default-encryption'), + 'enabled': KeyInfo(default=False), + 'ipsec-secret': KeyInfo(default=''), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1450), + 'max-mtu': KeyInfo(default=1450), + 'max-sessions': KeyInfo(default='unlimited'), + 'mrru': KeyInfo(default='disabled'), + 'one-session-per-host': KeyInfo(default=False), + 'use-ipsec': KeyInfo(default=False), + }, + ), + ('interface', 'ovpn-server', 'server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'auth': KeyInfo(), + 'cipher': KeyInfo(), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'mac-address': KeyInfo(), + 'max-mtu': KeyInfo(default=1500), + 'mode': KeyInfo(default='ip'), + 'netmask': KeyInfo(default=24), + 'port': KeyInfo(default=1194), + 'require-client-certificate': KeyInfo(default=False), + }, + ), + ('interface', 'pptp-server', 'server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'authentication': KeyInfo(default='mschap1,mschap2'), + 'default-profile': KeyInfo(default='default-encryption'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1450), + 'max-mtu': KeyInfo(default=1450), + 'mrru': KeyInfo(default='disabled'), + }, + ), + ('interface', 'sstp-server', 'server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'certificate': KeyInfo(default='none'), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'force-aes': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'max-mru': KeyInfo(default=1500), + 'max-mtu': KeyInfo(default=1500), + 'mrru': KeyInfo(default='disabled'), + 'pfs': KeyInfo(default=False), + 'port': KeyInfo(default=443), + 'tls-version': KeyInfo(default='any'), + 'verify-client-certificate': KeyInfo(default='no'), + }, + ), + ('interface', 'wireless', 'align'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'active-mode': KeyInfo(default=True), + 'audio-max': KeyInfo(default=-20), + 'audio-min': KeyInfo(default=-100), + 'audio-monitor': KeyInfo(default='00:00:00:00:00:00'), + 'filter-mac': KeyInfo(default='00:00:00:00:00:00'), + 'frame-size': KeyInfo(default=300), + 'frames-per-second': KeyInfo(default=25), + 'receive-all': KeyInfo(default=False), + 'ssid-all': KeyInfo(default=False), + }, + ), + ('interface', 'wireless', 'cap'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'caps-man-addresses': KeyInfo(default=''), + 'caps-man-certificate-common-names': KeyInfo(default=''), + 'caps-man-names': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'discovery-interfaces': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'interfaces': KeyInfo(default=''), + 'lock-to-caps-man': KeyInfo(default=False), + 'static-virtual': KeyInfo(default=False), + }, + ), + ('interface', 'wireless', 'sniffer'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'channel-time': KeyInfo(default='200ms'), + 'file-limit': KeyInfo(default=10), + 'file-name': KeyInfo(default=''), + 'memory-limit': KeyInfo(default=10), + 'multiple-channels': KeyInfo(default=False), + 'only-headers': KeyInfo(default=False), + 'receive-errors': KeyInfo(default=False), + 'streaming-enabled': KeyInfo(default=False), + 'streaming-max-rate': KeyInfo(default=0), + 'streaming-server': KeyInfo(default='0.0.0.0'), + }, + ), + ('interface', 'wireless', 'snooper'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'channel-time': KeyInfo(default='200ms'), + 'multiple-channels': KeyInfo(default=True), + 'receive-errors': KeyInfo(default=False), + }, + ), + ('ip', 'accounting'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'account-local-traffic': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'threshold': KeyInfo(default=256), + }, + ), + ('ip', 'accounting', 'web-access'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accessible-via-web': KeyInfo(default=False), + 'address': KeyInfo(default='0.0.0.0/0'), + }, + ), + ('ip', 'address'): APIData( + fully_understood=True, + primary_keys=('address', 'interface', ), + fields={ + 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'network': KeyInfo(automatically_computed_from=('address', )), + }, + ), + ('ip', 'cloud'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'ddns-enabled': KeyInfo(default=False), + 'ddns-update-interval': KeyInfo(default='none'), + 'update-time': KeyInfo(default=True), + }, + ), + ('ip', 'cloud', 'advanced'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'use-local-address': KeyInfo(default=False), + }, + ), + ('ip', 'dhcp-client'): APIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'add-default-route': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dhcp-options': KeyInfo(default='hostname,clientid'), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'use-peer-dns': KeyInfo(default=True), + 'use-peer-ntp': KeyInfo(default=True), + }, + ), + ('ip', 'dhcp-server', 'config'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'store-leases-disk': KeyInfo(default='5m'), + }, + ), + ('ip', 'dhcp-server', 'lease'): APIData( + fully_understood=True, + primary_keys=('server', 'address', ), + fields={ + 'address': KeyInfo(), + 'address-lists': KeyInfo(default=''), + 'always-broadcast': KeyInfo(), + 'client-id': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True, remove_value=''), + 'server': KeyInfo(), + }, + ), + ('ip', 'dhcp-server', 'network'): APIData( + fully_understood=True, + primary_keys=('address', ), + fields={ + 'address': KeyInfo(), + 'caps-manager': KeyInfo(default=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'dns-server': KeyInfo(default=''), + 'gateway': KeyInfo(automatically_computed_from=('address', )), + 'netmask': KeyInfo(automatically_computed_from=('address', )), + 'ntp-server': KeyInfo(default=''), + 'wins-server': KeyInfo(default=''), + }, + ), + ('ip', 'dns'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-remote-requests': KeyInfo(), + 'cache-max-ttl': KeyInfo(default='1w'), + 'cache-size': KeyInfo(default='2048KiB'), + 'max-concurrent-queries': KeyInfo(default=100), + 'max-concurrent-tcp-sessions': KeyInfo(default=20), + 'max-udp-packet-size': KeyInfo(default=4096), + 'query-server-timeout': KeyInfo(default='2s'), + 'query-total-timeout': KeyInfo(default='10s'), + 'servers': KeyInfo(default=''), + 'use-doh-server': KeyInfo(default=''), + 'verify-doh-cert': KeyInfo(default=False), + }, + ), + ('ip', 'dns', 'static'): APIData( + fully_understood=True, + stratify_keys=('name', ), + fields={ + 'address': KeyInfo(), + 'cname': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'forward-to': KeyInfo(), + 'mx-exchange': KeyInfo(), + 'mx-preference': KeyInfo(), + 'name': KeyInfo(required=True), + 'ns': KeyInfo(), + 'srv-port': KeyInfo(), + 'srv-priority': KeyInfo(), + 'srv-target': KeyInfo(), + 'srv-weight': KeyInfo(), + 'text': KeyInfo(), + 'ttl': KeyInfo(default='1d'), + 'type': KeyInfo(), + }, + ), + ('ip', 'firewall', 'address-list'): APIData( + fully_understood=True, + primary_keys=('address', 'list', ), + fields={ + 'address': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'list': KeyInfo(), + }, + ), + ('ip', 'firewall', 'filter'): APIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-nat-state': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'p2p': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'routing-table': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), + ('ip', 'firewall', 'nat'): APIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dst-address': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'to-addresses': KeyInfo(can_disable=True), + 'to-ports': KeyInfo(can_disable=True), + }, + ), + ('ip', 'hotspot', 'user'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(), + 'name': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'xauth-use-radius': KeyInfo(default=False), + }, + ), + ('ip', 'proxy'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'always-from-cache': KeyInfo(default=False), + 'anonymous': KeyInfo(default=False), + 'cache-administrator': KeyInfo(default='webmaster'), + 'cache-hit-dscp': KeyInfo(default=4), + 'cache-on-disk': KeyInfo(default=False), + 'cache-path': KeyInfo(default='web-proxy'), + 'enabled': KeyInfo(default=False), + 'max-cache-object-size': KeyInfo(default='2048KiB'), + 'max-cache-size': KeyInfo(default='unlimited'), + 'max-client-connections': KeyInfo(default=600), + 'max-fresh-time': KeyInfo(default='3d'), + 'max-server-connections': KeyInfo(default=600), + 'parent-proxy': KeyInfo(default='::'), + 'parent-proxy-port': KeyInfo(default=0), + 'port': KeyInfo(default=8080), + 'serialize-connections': KeyInfo(default=False), + 'src-address': KeyInfo(default='::'), + }, + ), + ('ip', 'smb'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-guests': KeyInfo(default=True), + 'comment': KeyInfo(default='MikrotikSMB'), + 'domain': KeyInfo(default='MSHOME'), + 'enabled': KeyInfo(default=False), + 'interfaces': KeyInfo(default='all'), + }, + ), + ('ip', 'smb', 'shares'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'directory': KeyInfo(), + 'disabled': KeyInfo(), + 'max-sessions': KeyInfo(), + 'name': KeyInfo(), + }, + ), + ('ip', 'smb', 'users'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'name': KeyInfo(), + 'password': KeyInfo(), + 'read-only': KeyInfo(), + }, + ), + ('ip', 'socks'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'auth-method': KeyInfo(default='none'), + 'connection-idle-timeout': KeyInfo(default='2m'), + 'enabled': KeyInfo(default=False), + 'max-connections': KeyInfo(default=200), + 'port': KeyInfo(default=1080), + 'version': KeyInfo(default=4), + }, + ), + ('ip', 'ssh'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-none-crypto': KeyInfo(default=False), + 'always-allow-password-login': KeyInfo(default=False), + 'forwarding-enabled': KeyInfo(default=False), + 'host-key-size': KeyInfo(default=2048), + 'strong-crypto': KeyInfo(default=False), + }, + ), + ('ip', 'tftp', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'max-block-size': KeyInfo(default=4096), + }, + ), + ('ip', 'traffic-flow'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'active-flow-timeout': KeyInfo(default='30m'), + 'cache-entries': KeyInfo(default='32k'), + 'enabled': KeyInfo(default=False), + 'inactive-flow-timeout': KeyInfo(default='15s'), + 'interfaces': KeyInfo(default='all'), + 'packet-sampling': KeyInfo(default=False), + 'sampling-interval': KeyInfo(default=0), + 'sampling-space': KeyInfo(default=0), + }, + ), + ('ip', 'traffic-flow', 'ipfix'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'bytes': KeyInfo(default=True), + 'dst-address': KeyInfo(default=True), + 'dst-address-mask': KeyInfo(default=True), + 'dst-mac-address': KeyInfo(default=True), + 'dst-port': KeyInfo(default=True), + 'first-forwarded': KeyInfo(default=True), + 'gateway': KeyInfo(default=True), + 'icmp-code': KeyInfo(default=True), + 'icmp-type': KeyInfo(default=True), + 'igmp-type': KeyInfo(default=True), + 'in-interface': KeyInfo(default=True), + 'ip-header-length': KeyInfo(default=True), + 'ip-total-length': KeyInfo(default=True), + 'ipv6-flow-label': KeyInfo(default=True), + 'is-multicast': KeyInfo(default=True), + 'last-forwarded': KeyInfo(default=True), + 'nat-dst-address': KeyInfo(default=True), + 'nat-dst-port': KeyInfo(default=True), + 'nat-events': KeyInfo(default=False), + 'nat-src-address': KeyInfo(default=True), + 'nat-src-port': KeyInfo(default=True), + 'out-interface': KeyInfo(default=True), + 'packets': KeyInfo(default=True), + 'protocol': KeyInfo(default=True), + 'src-address': KeyInfo(default=True), + 'src-address-mask': KeyInfo(default=True), + 'src-mac-address': KeyInfo(default=True), + 'src-port': KeyInfo(default=True), + 'sys-init-time': KeyInfo(default=True), + 'tcp-ack-num': KeyInfo(default=True), + 'tcp-flags': KeyInfo(default=True), + 'tcp-seq-num': KeyInfo(default=True), + 'tcp-window-size': KeyInfo(default=True), + 'tos': KeyInfo(default=True), + 'ttl': KeyInfo(default=True), + 'udp-length': KeyInfo(default=True), + }, + ), + ('ip', 'upnp'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-disable-external-interface': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'show-dummy-rule': KeyInfo(default=True), + }, + ), + ('ipv6', 'dhcp-client'): APIData( + fully_understood=True, + primary_keys=('interface', 'request'), + fields={ + 'add-default-route': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dhcp-options': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'pool-name': KeyInfo(required=True), + 'pool-prefix-length': KeyInfo(default=64), + 'prefix-hint': KeyInfo(default='::/0'), + 'request': KeyInfo(), + 'use-peer-dns': KeyInfo(default=True), + }, + ), + ('ipv6', 'firewall', 'address-list'): APIData( + fully_understood=True, + primary_keys=('address', 'list', ), + fields={ + 'address': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'dynamic': KeyInfo(default=False), + 'list': KeyInfo(), + }, + ), + ('ipv6', 'firewall', 'filter'): APIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + }, + ), + ('ipv6', 'nd'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'advertise-dns': KeyInfo(), + 'advertise-mac-address': KeyInfo(), + 'disabled': KeyInfo(), + 'hop-limit': KeyInfo(), + 'interface': KeyInfo(), + 'managed-address-configuration': KeyInfo(), + 'mtu': KeyInfo(), + 'other-configuration': KeyInfo(), + 'ra-delay': KeyInfo(), + 'ra-interval': KeyInfo(), + 'ra-lifetime': KeyInfo(), + 'reachable-time': KeyInfo(), + 'retransmit-interval': KeyInfo(), + }, + ), + ('ipv6', 'nd', 'prefix', 'default'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'autonomous': KeyInfo(default=True), + 'preferred-lifetime': KeyInfo(default='1w'), + 'valid-lifetime': KeyInfo(default='4w2d'), + }, + ), + ('ipv6', 'route'): APIData( + fields={ + 'bgp-as-path': KeyInfo(can_disable=True), + 'bgp-atomic-aggregate': KeyInfo(can_disable=True), + 'bgp-communities': KeyInfo(can_disable=True), + 'bgp-local-pref': KeyInfo(can_disable=True), + 'bgp-med': KeyInfo(can_disable=True), + 'bgp-origin': KeyInfo(can_disable=True), + 'bgp-prepend': KeyInfo(can_disable=True), + 'check-gateway': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'distance': KeyInfo(), + 'dst-address': KeyInfo(), + 'gateway': KeyInfo(), + 'route-tag': KeyInfo(can_disable=True), + 'scope': KeyInfo(), + 'target-scope': KeyInfo(), + }, + ), + ('mpls', ): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'dynamic-label-range': KeyInfo(default='16-1048575'), + 'propagate-ttl': KeyInfo(default=True), + }, + ), + ('mpls', 'interface'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'interface': KeyInfo(), + 'mpls-mtu': KeyInfo(), + }, + ), + ('mpls', 'ldp'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-for-default-route': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'hop-limit': KeyInfo(default=255), + 'loop-detect': KeyInfo(default=False), + 'lsr-id': KeyInfo(default='0.0.0.0'), + 'path-vector-limit': KeyInfo(default=255), + 'transport-address': KeyInfo(default='0.0.0.0'), + 'use-explicit-null': KeyInfo(default=False), + }, + ), + ('port', 'firmware'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'directory': KeyInfo(default='firmware'), + 'ignore-directip-modem': KeyInfo(default=False), + }, + ), + ('ppp', 'aaa'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'use-circuit-id-in-nas-port-id': KeyInfo(default=False), + 'use-radius': KeyInfo(default=False), + }, + ), + ('radius', 'incoming'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accept': KeyInfo(default=False), + 'port': KeyInfo(default=3799), + }, + ), + ('routing', 'bfd', 'interface'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'interface': KeyInfo(), + 'interval': KeyInfo(), + 'min-rx': KeyInfo(), + 'multiplier': KeyInfo(), + }, + ), + ('routing', 'mme'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'bidirectional-timeout': KeyInfo(default=2), + 'gateway-class': KeyInfo(default='none'), + 'gateway-keepalive': KeyInfo(default='1m'), + 'gateway-selection': KeyInfo(default='no-gateway'), + 'origination-interval': KeyInfo(default='5s'), + 'preferred-gateway': KeyInfo(default='0.0.0.0'), + 'timeout': KeyInfo(default='1m'), + 'ttl': KeyInfo(default=50), + }, + ), + ('routing', 'rip'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-default': KeyInfo(default='never'), + 'garbage-timer': KeyInfo(default='2m'), + 'metric-bgp': KeyInfo(default=1), + 'metric-connected': KeyInfo(default=1), + 'metric-default': KeyInfo(default=1), + 'metric-ospf': KeyInfo(default=1), + 'metric-static': KeyInfo(default=1), + 'redistribute-bgp': KeyInfo(default=False), + 'redistribute-connected': KeyInfo(default=False), + 'redistribute-ospf': KeyInfo(default=False), + 'redistribute-static': KeyInfo(default=False), + 'routing-table': KeyInfo(default='main'), + 'timeout-timer': KeyInfo(default='3m'), + 'update-timer': KeyInfo(default='30s'), + }, + ), + ('routing', 'ripng'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-default': KeyInfo(default='never'), + 'garbage-timer': KeyInfo(default='2m'), + 'metric-bgp': KeyInfo(default=1), + 'metric-connected': KeyInfo(default=1), + 'metric-default': KeyInfo(default=1), + 'metric-ospf': KeyInfo(default=1), + 'metric-static': KeyInfo(default=1), + 'redistribute-bgp': KeyInfo(default=False), + 'redistribute-connected': KeyInfo(default=False), + 'redistribute-ospf': KeyInfo(default=False), + 'redistribute-static': KeyInfo(default=False), + 'timeout-timer': KeyInfo(default='3m'), + 'update-timer': KeyInfo(default='30s'), + }, + ), + ('snmp', ): APIData( + single_value=True, + fully_understood=True, + fields={ + 'contact': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'engine-id': KeyInfo(default=''), + 'location': KeyInfo(default=''), + 'src-address': KeyInfo(default='::'), + 'trap-community': KeyInfo(default='public'), + 'trap-generators': KeyInfo(default='temp-exception'), + 'trap-target': KeyInfo(default=''), + 'trap-version': KeyInfo(default=1), + }, + ), + ('system', 'clock'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'time-zone-autodetect': KeyInfo(default=True), + 'time-zone-name': KeyInfo(default='manual'), + }, + ), + ('system', 'clock', 'manual'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'dst-delta': KeyInfo(default='00:00'), + 'dst-end': KeyInfo(default='jan/01/1970 00:00:00'), + 'dst-start': KeyInfo(default='jan/01/1970 00:00:00'), + 'time-zone': KeyInfo(default='+00:00'), + }, + ), + ('system', 'identity'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'name': KeyInfo(default='Mikrotik'), + }, + ), + ('system', 'leds', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'all-leds-off': KeyInfo(default='never'), + }, + ), + ('system', 'note'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'note': KeyInfo(default=''), + 'show-at-login': KeyInfo(default=True), + }, + ), + ('system', 'ntp', 'client'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=False), + 'primary-ntp': KeyInfo(default='0.0.0.0'), + 'secondary-ntp': KeyInfo(default='0.0.0.0'), + 'server-dns-names': KeyInfo(default=''), + }, + ), + ('system', 'package', 'update'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'channel': KeyInfo(default='stable'), + }, + ), + ('system', 'routerboard', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'auto-upgrade': KeyInfo(default=False), + 'baud-rate': KeyInfo(default=115200), + 'boot-delay': KeyInfo(default='2s'), + 'boot-device': KeyInfo(default='nand-if-fail-then-ethernet'), + 'boot-protocol': KeyInfo(default='bootp'), + 'enable-jumper-reset': KeyInfo(default=True), + 'enter-setup-on': KeyInfo(default='any-key'), + 'force-backup-booter': KeyInfo(default=False), + 'protected-routerboot': KeyInfo(default='disabled'), + 'reformat-hold-button': KeyInfo(default='20s'), + 'reformat-hold-button-max': KeyInfo(default='10m'), + 'silent-boot': KeyInfo(default=False), + }, + ), + ('system', 'upgrade', 'mirror'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'check-interval': KeyInfo(default='1d'), + 'enabled': KeyInfo(default=False), + 'primary-server': KeyInfo(default='0.0.0.0'), + 'secondary-server': KeyInfo(default='0.0.0.0'), + 'user': KeyInfo(default=''), + }, + ), + ('system', 'watchdog'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'auto-send-supout': KeyInfo(default=False), + 'automatic-supout': KeyInfo(default=True), + 'ping-start-after-boot': KeyInfo(default='5m'), + 'ping-timeout': KeyInfo(default='1m'), + 'watch-address': KeyInfo(default='none'), + 'watchdog-timer': KeyInfo(default=True), + }, + ), + ('tool', 'bandwidth-server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allocate-udp-ports-from': KeyInfo(default=2000), + 'authenticate': KeyInfo(default=True), + 'enabled': KeyInfo(default=True), + 'max-sessions': KeyInfo(default=100), + }, + ), + ('tool', 'e-mail'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'address': KeyInfo(default='0.0.0.0'), + 'from': KeyInfo(default='<>'), + 'password': KeyInfo(default=''), + 'port': KeyInfo(default=25), + 'start-tls': KeyInfo(default=False), + 'user': KeyInfo(default=''), + }, + ), + ('tool', 'graphing'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'page-refresh': KeyInfo(default=300), + 'store-every': KeyInfo(default='5min'), + }, + ), + ('tool', 'mac-server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-interface-list': KeyInfo(), + }, + ), + ('tool', 'mac-server', 'mac-winbox'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-interface-list': KeyInfo(), + }, + ), + ('tool', 'mac-server', 'ping'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=True), + }, + ), + ('tool', 'romon'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=False), + 'id': KeyInfo(default='00:00:00:00:00:00'), + 'secrets': KeyInfo(default=''), + }, + ), + ('tool', 'romon', 'port'): APIData( + fields={ + 'cost': KeyInfo(), + 'disabled': KeyInfo(), + 'forbid': KeyInfo(), + 'interface': KeyInfo(), + 'secrets': KeyInfo(), + }, + ), + ('tool', 'sms'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-number': KeyInfo(default=''), + 'auto-erase': KeyInfo(default=False), + 'channel': KeyInfo(default=0), + 'port': KeyInfo(default='none'), + 'receive-enabled': KeyInfo(default=False), + 'secret': KeyInfo(default=''), + 'sim-pin': KeyInfo(default=''), + }, + ), + ('tool', 'sniffer'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'file-limit': KeyInfo(default='1000KiB'), + 'file-name': KeyInfo(default=''), + 'filter-cpu': KeyInfo(default=''), + 'filter-direction': KeyInfo(default='any'), + 'filter-interface': KeyInfo(default=''), + 'filter-ip-address': KeyInfo(default=''), + 'filter-ip-protocol': KeyInfo(default=''), + 'filter-ipv6-address': KeyInfo(default=''), + 'filter-mac-address': KeyInfo(default=''), + 'filter-mac-protocol': KeyInfo(default=''), + 'filter-operator-between-entries': KeyInfo(default='or'), + 'filter-port': KeyInfo(default=''), + 'filter-size': KeyInfo(default=''), + 'filter-stream': KeyInfo(default=False), + 'memory-limit': KeyInfo(default='100KiB'), + 'memory-scroll': KeyInfo(default=True), + 'only-headers': KeyInfo(default=False), + 'streaming-enabled': KeyInfo(default=False), + 'streaming-server': KeyInfo(default='0.0.0.0:37008'), + }, + ), + ('tool', 'traffic-generator'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'latency-distribution-max': KeyInfo(default='100us'), + 'measure-out-of-order': KeyInfo(default=True), + 'stats-samples-to-keep': KeyInfo(default=100), + 'test-id': KeyInfo(default=0), + }, + ), + ('user', 'aaa'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'default-group': KeyInfo(default='read'), + 'exclude-groups': KeyInfo(default=''), + 'interim-update': KeyInfo(default='0s'), + 'use-radius': KeyInfo(default=False), + }, + ), + ('queue', 'interface'): APIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'name': KeyInfo(required=True), + 'queue': KeyInfo(required=True), + }, + ), + ('interface', 'ethernet', 'switch'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'cpu-flow-control': KeyInfo(default=True), + 'mirror-source': KeyInfo(default='none'), + 'mirror-target': KeyInfo(default='none'), + 'name': KeyInfo(), + }, + ), + ('interface', 'ethernet', 'switch', 'port'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'default-vlan-id': KeyInfo(), + 'name': KeyInfo(), + 'vlan-header': KeyInfo(default='leave-as-is'), + 'vlan-mode': KeyInfo(default='disabled'), + }, + ), + ('ip', 'dhcp-client', 'option'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'code': KeyInfo(), + 'name': KeyInfo(), + 'value': KeyInfo(), + }, + ), + ('ppp', 'profile'): APIData( + has_identifier=True, + fields={ + 'address-list': KeyInfo(), + 'bridge': KeyInfo(can_disable=True), + 'bridge-horizon': KeyInfo(can_disable=True), + 'bridge-learning': KeyInfo(), + 'bridge-path-cost': KeyInfo(can_disable=True), + 'bridge-port-priority': KeyInfo(can_disable=True), + 'change-tcp-mss': KeyInfo(), + 'dns-server': KeyInfo(can_disable=True), + 'idle-timeout': KeyInfo(can_disable=True), + 'incoming-filter': KeyInfo(can_disable=True), + 'insert-queue-before': KeyInfo(can_disable=True), + 'interface-list': KeyInfo(can_disable=True), + 'local-address': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'on-down': KeyInfo(), + 'on-up': KeyInfo(), + 'only-one': KeyInfo(), + 'outgoing-filter': KeyInfo(can_disable=True), + 'parent-queue': KeyInfo(can_disable=True), + 'queue-type': KeyInfo(can_disable=True), + 'rate-limit': KeyInfo(can_disable=True), + 'remote-address': KeyInfo(can_disable=True), + 'session-timeout': KeyInfo(can_disable=True), + 'use-compression': KeyInfo(), + 'use-encryption': KeyInfo(), + 'use-ipv6': KeyInfo(), + 'use-mpls': KeyInfo(), + 'use-upnp': KeyInfo(), + 'wins-server': KeyInfo(can_disable=True), + }, + ), + ('queue', 'type'): APIData( + has_identifier=True, + fields={ + 'kind': KeyInfo(), + 'mq-pfifo-limit': KeyInfo(), + 'name': KeyInfo(), + 'pcq-burst-rate': KeyInfo(), + 'pcq-burst-threshold': KeyInfo(), + 'pcq-burst-time': KeyInfo(), + 'pcq-classifier': KeyInfo(), + 'pcq-dst-address-mask': KeyInfo(), + 'pcq-dst-address6-mask': KeyInfo(), + 'pcq-limit': KeyInfo(), + 'pcq-rate': KeyInfo(), + 'pcq-src-address-mask': KeyInfo(), + 'pcq-src-address6-mask': KeyInfo(), + 'pcq-total-limit': KeyInfo(), + 'pfifo-limit': KeyInfo(), + 'red-avg-packet': KeyInfo(), + 'red-burst': KeyInfo(), + 'red-limit': KeyInfo(), + 'red-max-threshold': KeyInfo(), + 'red-min-threshold': KeyInfo(), + 'sfq-allot': KeyInfo(), + 'sfq-perturb': KeyInfo(), + }, + ), + ('routing', 'bgp', 'instance'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'as': KeyInfo(), + 'client-to-client-reflection': KeyInfo(), + 'cluster-id': KeyInfo(can_disable=True), + 'confederation': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'ignore-as-path-len': KeyInfo(), + 'name': KeyInfo(), + 'out-filter': KeyInfo(), + 'redistribute-connected': KeyInfo(), + 'redistribute-ospf': KeyInfo(), + 'redistribute-other-bgp': KeyInfo(), + 'redistribute-rip': KeyInfo(), + 'redistribute-static': KeyInfo(), + 'router-id': KeyInfo(), + 'routing-table': KeyInfo(), + }, + ), + ('system', 'logging', 'action'): APIData( + has_identifier=True, + fields={ + 'bsd-syslog': KeyInfo(), + 'disk-file-count': KeyInfo(), + 'disk-file-name': KeyInfo(), + 'disk-lines-per-file': KeyInfo(), + 'disk-stop-on-full': KeyInfo(), + 'memory-lines': KeyInfo(), + 'memory-stop-on-full': KeyInfo(), + 'name': KeyInfo(), + 'remember': KeyInfo(), + 'remote': KeyInfo(), + 'remote-port': KeyInfo(), + 'src-address': KeyInfo(), + 'syslog-facility': KeyInfo(), + 'syslog-severity': KeyInfo(), + 'syslog-time-format': KeyInfo(), + 'target': KeyInfo(), + }, + ), + ('user', 'group'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'name': KeyInfo(), + 'policy': KeyInfo(), + 'skin': KeyInfo(default='default'), + }, + ), + ('caps-man', 'manager'): APIData( + single_value=True, + fields={ + 'ca-certificate': KeyInfo(default='none'), + 'certificate': KeyInfo(default='none'), + 'enabled': KeyInfo(default=False), + 'package-path': KeyInfo(default=''), + 'require-peer-certificate': KeyInfo(default=False), + 'upgrade-policy': KeyInfo(default='none'), + }, + ), + ('ip', 'firewall', 'service-port'): APIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'ports': KeyInfo(), + 'sip-direct-media': KeyInfo(), + 'sip-timeout': KeyInfo(), + }, + ), + ('ip', 'hotspot', 'service-port'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'ports': KeyInfo(), + }, + ), + ('ip', 'ipsec', 'policy'): APIData( + has_identifier=True, + fields={ + 'disabled': KeyInfo(), + 'dst-address': KeyInfo(), + 'group': KeyInfo(), + 'proposal': KeyInfo(), + 'protocol': KeyInfo(), + 'src-address': KeyInfo(), + 'template': KeyInfo(), + }, + ), + ('ip', 'service'): APIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'certificate': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'port': KeyInfo(), + 'tls-version': KeyInfo(), + }, + ), + ('system', 'logging'): APIData( + has_identifier=True, + fields={ + 'action': KeyInfo(), + 'disabled': KeyInfo(), + 'prefix': KeyInfo(), + 'topics': KeyInfo(), + }, + ), + ('system', 'resource', 'irq'): APIData( + has_identifier=True, + fields={ + 'cpu': KeyInfo(), + }, + ), +} diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py new file mode 100644 index 0000000..0d4a282 --- /dev/null +++ b/plugins/modules/api_find_and_modify.py @@ -0,0 +1,312 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2022, Felix Fontein +# GNU General Public License v3.0+ https://www.gnu.org/licenses/gpl-3.0.txt + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: api_find_and_modify +author: + - "Felix Fontein (@felixfontein)" +short_description: Find and modify information using the API +version_added: 2.1.0 +description: + - Allows to find entries for a path by conditions and modify the values of these entries. +notes: + - "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that + there are at least N such values, you can use I(require_matches_min=N) together with I(allow_no_matches=true). + This will make the module fail if there are less than N such entries, but not if there is no match. The latter case + is needed for idempotency of the task: once the values have been changed, there should be no further match." + - Supports I(check_mode). +extends_documentation_fragment: + - community.routeros.api +options: + path: + description: + - Path to query. + - An example value is C(ip address). This is equivalent to running C(/ip address) in the RouterOS CLI. + required: true + type: str + find: + description: + - Fields to search for. + - The module will only consider entries in the given I(path) that match all fields provided here. + - Use YAML C(~), or prepend keys with C(!), to specify an unset value. + - Note that if the dictionary specified here is empty, every entry in the path will be matched. + required: true + type: dict + values: + description: + - On all entries matching the conditions in I(find), set the keys of this option to the values specified here. + - Use YAML C(~), or prepend keys with C(!), to specify to unset a value. + required: true + type: dict + require_matches_min: + description: + - Make sure that there are no less matches than this number. + - If there are less matches, fail instead of modifying anything. + type: int + default: 0 + require_matches_max: + description: + - Make sure that there are no more matches than this number. + - If there are more matches, fail instead of modifying anything. + - If not specified, there is no upper limit. + type: int + allow_no_matches: + description: + - Whether to allow that no match is found. + - If not specified, this value is induced from whether I(require_matches_min) is 0 or larger. + type: bool +seealso: + - module: community.routeros.api +''' + +EXAMPLES = ''' +--- +- name: Rename bridge from 'bridge' to 'my-bridge' + community.routeros.api_find_and_modify: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: interface bridge + find: + name: bridge + values: + name: my-bridge + +- name: Change IP address to 192.168.1.1 for interface bridge - assuming there is only one + community.routeros.api_find_and_modify: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: ip address + find: + interface: bridge + values: + address: "192.168.1.1/24" + # If there are zero entries, or more than one: fail! We expected that + # exactly one is configured. + require_matches_min: 1 + require_matches_max: 1 +''' + +RETURN = ''' +--- +old_data: + description: + - A list of all elements for the current path before a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: success +new_data: + description: + - A list of all elements for the current path after a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.1.1/24" + comment: awesome + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.1.0 + type: list + elements: dict + returned: success +match_count: + description: + - The number of entries that matched the criteria in I(find). + sample: 1 + type: int + returned: success +modify__count: + description: + - The number of entries that were modified. + sample: 1 + type: int + returned: success +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils.api import ( + api_argument_spec, + check_has_library, + create_api, +) + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( + split_path, +) + +try: + from librouteros.exceptions import LibRouterosError +except Exception: + # Handled in api module_utils + pass + + +def compose_api_path(api, path): + api_path = api.path() + for p in path: + api_path = api_path.join(p) + return api_path + + +DISABLED_MEANS_EMPTY_STRING = ('comment', ) + + +def main(): + module_args = dict( + path=dict(type='str', required=True), + find=dict(type='dict', required=True), + values=dict(type='dict', required=True), + require_matches_min=dict(type='int', default=0), + require_matches_max=dict(type='int'), + allow_no_matches=dict(type='bool'), + ) + module_args.update(api_argument_spec()) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + if module.params['allow_no_matches'] is None: + module.params['allow_no_matches'] = module.params['require_matches_min'] <= 0 + + find = module.params['find'] + for key, value in sorted(find.items()): + if key.startswith('!'): + key = key[1:] + if value not in (None, ''): + module.fail_json(msg='The value for "!{key}" in `find` must not be non-trivial!'.format(key=key)) + if key in find: + module.fail_json(msg='`find` must not contain both "{key}" and "!{key}"!'.format(key=key)) + values = module.params['values'] + for key, value in sorted(values.items()): + if key.startswith('!'): + key = key[1:] + if value not in (None, ''): + module.fail_json(msg='The value for "!{key}" in `values` must not be non-trivial!'.format(key=key)) + if key in values: + module.fail_json(msg='`values` must not contain both "{key}" and "!{key}"!'.format(key=key)) + + check_has_library(module) + api = create_api(module) + + path = split_path(module.params['path']) + + api_path = compose_api_path(api, path) + + old_data = list(api_path) + new_data = [entry.copy() for entry in old_data] + + # Find matching entries + matching_entries = [] + for index, entry in enumerate(new_data): + matches = True + for key, value in find.items(): + if key.startswith('!'): + # Allow to specify keys that should not be present by prepending '!' + key = key[1:] + value = None + current_value = entry.get(key) + if key in DISABLED_MEANS_EMPTY_STRING and value == '' and current_value is None: + current_value = value + if current_value != value: + matches = False + break + if matches: + matching_entries.append((index, entry)) + + # Check whether the correct amount of entries was found + if matching_entries: + if len(matching_entries) < module.params['require_matches_min']: + module.fail_json(msg='Found %d entries, but expected at least %d' % (len(matching_entries), module.params['require_matches_min'])) + if module.params['require_matches_max'] is not None and len(matching_entries) > module.params['require_matches_max']: + module.fail_json(msg='Found %d entries, but expected at most %d' % (len(matching_entries), module.params['require_matches_max'])) + elif not module.params['allow_no_matches']: + module.fail_json(msg='Found no entries, but allow_no_matches=false') + + # Identify entries to update + modifications = [] + for index, entry in matching_entries: + modification = {} + for key, value in values.items(): + if key.startswith('!'): + # Allow to specify keys to remove by prepending '!' + key = key[1:] + value = None + current_value = entry.get(key) + if key in DISABLED_MEANS_EMPTY_STRING and value == '' and current_value is None: + current_value = value + if current_value != value: + if value is None: + disable_key = '!%s' % key + if key in DISABLED_MEANS_EMPTY_STRING: + disable_key = key + modification[disable_key] = '' + entry.pop(key, None) + else: + modification[key] = value + entry[key] = value + if modification: + if '.id' in entry: + modification['.id'] = entry['.id'] + modifications.append(modification) + + # Apply changes + if not module.check_mode and modifications: + for modification in modifications: + try: + api_path.update(**modification) + except LibRouterosError as e: + module.fail_json( + msg='Error while modifying for .id={id}: {error}'.format( + id=modification['.id'], + error=to_native(e), + ) + ) + new_data = list(api_path) + + # Produce return value + more = {} + if module._diff: + # Only include the matching values + more['diff'] = { + 'before': { + 'values': [old_data[index] for index, entry in matching_entries], + }, + 'after': { + 'values': [entry for index, entry in matching_entries], + }, + } + module.exit_json( + changed=bool(modifications), + old_data=old_data, + new_data=new_data, + match_count=len(matching_entries), + modify_count=len(modifications), + **more + ) + + +if __name__ == '__main__': + main() diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py new file mode 100644 index 0000000..5053ca9 --- /dev/null +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import pytest + +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( + APIData, + KeyInfo, + split_path, + join_path, +) + + +def test_api_data_errors(): + with pytest.raises(ValueError) as exc: + APIData() + assert exc.value.args[0] == 'fields must be provided' + + values = [ + ('primary_keys', []), + ('stratify_keys', []), + ('has_identifier', True), + ('single_value', True), + ('unknown_mechanism', True), + ] + + for index, (param, param_value) in enumerate(values): + for param2, param2_value in values[index + 1:]: + with pytest.raises(ValueError) as exc: + APIData(**{param: param_value, param2: param2_value}) + assert exc.value.args[0] == 'primary_keys, stratify_keys, has_identifier, single_value, and unknown_mechanism are mutually exclusive' + + with pytest.raises(ValueError) as exc: + APIData(unknown_mechanism=True, fully_understood=True) + assert exc.value.args[0] == 'unknown_mechanism and fully_understood cannot be combined' + + with pytest.raises(ValueError) as exc: + APIData(unknown_mechanism=True, fixed_entries=True) + assert exc.value.args[0] == 'fixed_entries can only be used with primary_keys' + + with pytest.raises(ValueError) as exc: + APIData(primary_keys=['foo'], fields={}) + assert exc.value.args[0] == 'Primary key foo must be in fields!' + + with pytest.raises(ValueError) as exc: + APIData(stratify_keys=['foo'], fields={}) + assert exc.value.args[0] == 'Stratify key foo must be in fields!' + + +def test_key_info_errors(): + values = [ + ('required', True), + ('default', ''), + ('automatically_computed_from', ()), + ('can_disable', True), + ] + + for index, (param, param_value) in enumerate(values): + for param2, param2_value in values[index + 1:]: + with pytest.raises(ValueError) as exc: + KeyInfo(**{param: param_value, param2: param2_value}) + assert exc.value.args[0] == 'required, default, automatically_computed_from, and can_disable are mutually exclusive' + + with pytest.raises(ValueError) as exc: + KeyInfo('foo') + assert exc.value.args[0] == 'KeyInfo() does not have positional arguments' + + with pytest.raises(ValueError) as exc: + KeyInfo(remove_value='') + assert exc.value.args[0] == 'remove_value can only be specified if can_disable=True' + + +SPLITTED_PATHS = [ + ('', [], ''), + (' ip ', ['ip'], 'ip'), + ('ip', ['ip'], 'ip'), + (' ip \t\n\raddress ', ['ip', 'address'], 'ip address'), +] + + +@pytest.mark.parametrize("joined_input, splitted, joined_output", SPLITTED_PATHS) +def test_join_split_path(joined_input, splitted, joined_output): + assert split_path(joined_input) == splitted + assert join_path(splitted) == joined_output diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index cef6586..edfa28a 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -17,6 +17,8 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS + class FakeLibRouterosError(Exception): def __init__(self, message): @@ -125,3 +127,110 @@ class Or(object): def str_return(self): return repr(self.args) + + +def _normalize_entry(entry, path_info): + for key, data in path_info.fields.items(): + if key not in entry and data.default is not None: + entry[key] = data.default + if data.can_disable: + if key in entry and entry[key] in (None, data.remove_value): + del entry[key] + if ('!%s' % key) in entry: + entry.pop(key, None) + del entry['!%s' % key] + + +def massage_expected_result_data(values, path, keep_all=False): + path_info = PATHS[path] + values = [entry.copy() for entry in values] + for entry in values: + _normalize_entry(entry, path_info) + if not keep_all: + for key in list(entry): + if key == '.id' or key in path_info.fields: + continue + del entry[key] + return values + + +class Path(object): + def __init__(self, path, initial_values, read_only=False): + self._path = path + self._path_info = PATHS[path] + self._values = [entry.copy() for entry in initial_values] + for entry in self._values: + _normalize_entry(entry, self._path_info) + self._new_id_counter = 0 + self._read_only = read_only + + def __iter__(self): + return [entry.copy() for entry in self._values].__iter__() + + def _find_id(self, id, required=False): + for index, entry in enumerate(self._values): + if entry['.id'] == id: + return index + if required: + raise FakeLibRouterosError('Cannot find key "%s"' % id) + return None + + def add(self, **kwargs): + if self._path_info.fixed_entries or self._path_info.single_value: + raise Exception('Cannot add entries') + if self._read_only: + raise Exception('Modifying read-only path: add %s' % repr(kwargs)) + if '.id' in kwargs: + raise Exception('Trying to create new entry with ".id" field: %s' % repr(kwargs)) + self._new_id_counter += 1 + id = '*NEW%d' % self._new_id_counter + entry = { + '.id': id, + } + entry.update(kwargs) + _normalize_entry(entry, self._path_info) + self._values.append(entry) + return id + + def remove(self, *args): + if self._path_info.fixed_entries or self._path_info.single_value: + raise Exception('Cannot remove entries') + if self._read_only: + raise Exception('Modifying read-only path: remove %s' % repr(args)) + for id in args: + index = self._find_id(id, required=True) + del self._values[index] + + def update(self, **kwargs): + if self._read_only: + raise Exception('Modifying read-only path: update %s' % repr(kwargs)) + if self._path_info.single_value: + index = 0 + else: + index = self._find_id(kwargs['.id'], required=True) + entry = self._values[index] + entry.update(kwargs) + _normalize_entry(entry, self._path_info) + + def __call__(self, command, *args, **kwargs): + if self._read_only: + raise Exception('Modifying read-only path: "%s" %s %s' % (command, repr(args), repr(kwargs))) + if command != 'move': + raise FakeLibRouterosError('Unsupported command "%s"' % command) + if self._path_info.fixed_entries or self._path_info.single_value: + raise Exception('Cannot move entries') + yield None # make sure that nothing happens if the result isn't consumed + source_index = self._find_id(kwargs.pop('numbers'), required=True) + entry = self._values.pop(source_index) + dest_index = self._find_id(kwargs.pop('destination'), required=True) + self._values.insert(dest_index, entry) + + +def create_fake_path(path, initial_values, read_only=False): + def create(api, called_path): + called_path = tuple(called_path) + if path != called_path: + raise AssertionError('Expected {path}, got {called_path}'.format(path=path, called_path=called_path)) + return Path(path, initial_values, read_only=read_only) + + return create diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py new file mode 100644 index 0000000..5655d02 --- /dev/null +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -0,0 +1,666 @@ +# 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 + +import json +import pytest + +from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( + FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, +) +from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase +from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS +from ansible_collections.community.routeros.plugins.modules import api_find_and_modify + + +START_IP_DNS_STATIC = [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'dynamic': False, + }, + { + '.id': '*7', + 'comment': '', + 'name': 'foo', + 'address': '192.168.88.2', + 'dynamic': False, + }, +] + +START_IP_DNS_STATIC_OLD_DATA = massage_expected_result_data(START_IP_DNS_STATIC, ('ip', 'dns', 'static'), keep_all=True) + +START_IP_FIREWALL_FILTER = [ + { + '.id': '*2', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + 'protocol': 'icmp', + }, + { + '.id': '*3', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + 'connection-state': 'established', + }, + { + '.id': '*4', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + 'connection-state': 'related', + }, + { + '.id': '*7', + 'action': 'drop', + 'chain': 'input', + 'comment': 'defconf', + 'in-interface': 'wan', + }, + { + '.id': '*8', + 'action': 'accept', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-state': 'established', + }, + { + '.id': '*9', + 'action': 'accept', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-state': 'related', + }, + { + '.id': '*A', + 'action': 'drop', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-status': 'invalid', + }, +] + +START_IP_FIREWALL_FILTER_OLD_DATA = massage_expected_result_data(START_IP_FIREWALL_FILTER, ('ip', 'firewall', 'filter'), keep_all=True) + + +class TestRouterosApiFindAndModifyModule(ModuleTestCase): + + def setUp(self): + super(TestRouterosApiFindAndModifyModule, self).setUp() + self.module = api_find_and_modify + self.module.LibRouterosError = FakeLibRouterosError + self.module.connect = MagicMock(new=fake_ros_api) + self.module.check_has_library = MagicMock() + self.patch_create_api = patch( + 'ansible_collections.community.routeros.plugins.modules.api_find_and_modify.create_api', + MagicMock(new=fake_ros_api)) + self.patch_create_api.start() + self.config_module_args = { + 'username': 'admin', + 'password': 'pаss', + 'hostname': '127.0.0.1', + } + + def tearDown(self): + self.patch_create_api.stop() + + def test_module_fail_when_required_args_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + set_module_args({}) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + + def test_invalid_disabled_and_enabled_option_in_find(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'comment': 'foo', + '!comment': None, + }, + 'values': { + 'comment': 'bar', + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], '`find` must not contain both "comment" and "!comment"!') + + def test_invalid_disabled_option_invalid_value_in_find(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + '!comment': 'gone', + }, + 'values': { + 'comment': 'bar', + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'The value for "!comment" in `find` must not be non-trivial!') + + def test_invalid_disabled_and_enabled_option_in_values(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': {}, + 'values': { + 'comment': 'foo', + '!comment': None, + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], '`values` must not contain both "comment" and "!comment"!') + + def test_invalid_disabled_option_invalid_value_in_values(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': {}, + 'values': { + '!comment': 'gone', + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'The value for "!comment" in `values` must not be non-trivial!') + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_change_invalid_zero(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'bam', + }, + 'values': { + 'name': 'baz', + }, + 'require_matches_min': 10, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Found no entries, but allow_no_matches=false') + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_change_invalid_too_few(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'router', + }, + 'values': { + 'name': 'foobar', + }, + 'require_matches_min': 10, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Found 2 entries, but expected at least 10') + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_change_invalid_too_many(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'router', + }, + 'values': { + 'name': 'foobar', + }, + 'require_matches_max': 1, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Found 2 entries, but expected at most 1') + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_change_idempotent_zero_matches_1(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'baz', + }, + 'values': { + 'name': 'bam', + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['match_count'], 0) + self.assertEqual(result['modify_count'], 0) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_change_idempotent_zero_matches_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'baz', + }, + 'values': { + 'name': 'bam', + }, + 'require_matches_min': 2, + 'allow_no_matches': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['match_count'], 0) + self.assertEqual(result['modify_count'], 0) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_idempotent_1(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + }, + 'values': { + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['match_count'], 3) + self.assertEqual(result['modify_count'], 0) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_idempotent_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'foo', + }, + 'values': { + 'comment': None, + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['match_count'], 1) + self.assertEqual(result['modify_count'], 0) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_change(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + 'name': 'foo', + }, + 'values': { + 'comment': 'bar', + }, + '_ansible_diff': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*7', + 'comment': 'bar', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual(result['diff']['before']['values'], [ + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual(result['diff']['after']['values'], [ + { + '.id': '*7', + 'comment': 'bar', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual(result['match_count'], 1) + self.assertEqual(result['modify_count'], 1) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_change_remove_comment_1(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + }, + 'values': { + 'comment': None, + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual('diff' in result, False) + self.assertEqual(result['match_count'], 3) + self.assertEqual(result['modify_count'], 1) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_change_remove_comment_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + }, + 'values': { + 'comment': '', + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual(result['match_count'], 3) + self.assertEqual(result['modify_count'], 1) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_change_remove_comment_3(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'find': { + }, + 'values': { + '!comment': None, + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + 'dynamic': False, + }, + ]) + self.assertEqual(result['match_count'], 3) + self.assertEqual(result['modify_count'], 1) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'firewall', 'filter'), START_IP_FIREWALL_FILTER)) + def test_change_remove_generic(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'find': { + 'chain': 'input', + '!protocol': '', + }, + 'values': { + '!connection-state': None, + }, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_FIREWALL_FILTER_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*2', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + 'protocol': 'icmp', + }, + { + '.id': '*3', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + }, + { + '.id': '*4', + 'action': 'accept', + 'chain': 'input', + 'comment': 'defconf', + }, + { + '.id': '*7', + 'action': 'drop', + 'chain': 'input', + 'comment': 'defconf', + 'in-interface': 'wan', + }, + { + '.id': '*8', + 'action': 'accept', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-state': 'established', + }, + { + '.id': '*9', + 'action': 'accept', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-state': 'related', + }, + { + '.id': '*A', + 'action': 'drop', + 'chain': 'forward', + 'comment': 'defconf', + 'connection-status': 'invalid', + }, + ]) + self.assertEqual(result['match_count'], 3) + self.assertEqual(result['modify_count'], 2) diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index f4f7b56..0b66e0a 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -1 +1,2 @@ unittest2 ; python_version <= '2.6' +ordereddict ; python_version <= '2.6' From 745219507193335da482d807ac6ac5e6ab735911 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 24 May 2022 18:39:30 +0200 Subject: [PATCH 038/365] Prepare 2.1.0 release. --- changelogs/fragments/2.1.0.yml | 1 + galaxy.yml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.1.0.yml diff --git a/changelogs/fragments/2.1.0.yml b/changelogs/fragments/2.1.0.yml new file mode 100644 index 0000000..50ba42f --- /dev/null +++ b/changelogs/fragments/2.1.0.yml @@ -0,0 +1 @@ +release_summary: Feature and bugfix release with new modules. diff --git a/galaxy.yml b/galaxy.yml index e24ac9a..bae2ab9 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -2,11 +2,12 @@ namespace: community name: routeros -version: 2.0.0 +version: 2.1.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) - Nikolay Dachev (github.com/NikolayDachev) + - Felix Fontein (github.com/felixfontein) description: Modules for MikroTik RouterOS license_file: COPYING tags: From 023f11f7e1711cd1ec079c0f7e8803a4e2109bea Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 24 May 2022 22:19:26 +0200 Subject: [PATCH 039/365] Add encoding option to API modules (#95) * Set encoding to UTF-8. * Add encoding parameter to API modules. * librouteros is now patched. --- changelogs/fragments/95-api-encoding.yml | 2 ++ plugins/doc_fragments/api.py | 7 +++++ plugins/module_utils/api.py | 27 ++++++++--------- plugins/modules/api.py | 37 +++++++++++++----------- plugins/modules/api_find_and_modify.py | 2 +- 5 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 changelogs/fragments/95-api-encoding.yml diff --git a/changelogs/fragments/95-api-encoding.yml b/changelogs/fragments/95-api-encoding.yml new file mode 100644 index 0000000..d3e0ea3 --- /dev/null +++ b/changelogs/fragments/95-api-encoding.yml @@ -0,0 +1,2 @@ +minor_changes: + - "api* modules - allow to set an encoding other than the default ASCII for communicating with the API (https://github.com/ansible-collections/community.routeros/pull/95)." diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index f436d64..6995c5c 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -63,6 +63,13 @@ options: - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). type: path version_added: 1.2.0 + encoding: + description: + - Use the specified encoding when communicating with the RouterOS device. + - Default is C(ASCII). Note that C(UTF-8) requires librouteros 3.2.1 or newer. + type: str + default: ASCII + version_added: 2.1.0 requirements: - librouteros - Python >= 3.6 (for librouteros) diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index f8b839f..7150dcc 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -43,10 +43,11 @@ def api_argument_spec(): validate_certs=dict(type='bool', default=True), validate_cert_hostname=dict(type='bool', default=False), ca_path=dict(type='path'), + encoding=dict(type='str', default='ASCII') ) -def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path): +def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding): '''Connect to RouterOS API.''' if not port: if use_tls: @@ -54,6 +55,13 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c else: port = 8728 try: + params = dict( + username=username, + password=password, + host=host, + port=port, + encoding=encoding, + ) if use_tls: ctx = ssl.create_default_context(cafile=ca_path) wrap_context = ctx.wrap_socket @@ -68,20 +76,8 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c def wrap_context(*args, **kwargs): kwargs.pop('server_hostname', None) return ctx.wrap_socket(*args, server_hostname=host, **kwargs) - api = connect( - username=username, - password=password, - host=host, - ssl_wrapper=wrap_context, - port=port, - ) - else: - api = connect( - username=username, - password=password, - host=host, - port=port, - ) + params['ssl_wrapper'] = wrap_context + api = connect(**params) except Exception as e: connection = { 'username': username, @@ -105,4 +101,5 @@ def create_api(module): module.params['validate_certs'], module.params['validate_cert_hostname'], module.params['ca_path'], + module.params['encoding'], ) diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 85dc704..ddd026c 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -329,23 +329,26 @@ class ROS_api_module: # create api base path self.api_path = self.api_add_path(self.api, self.path) - # api call's - if self.add: - self.api_add() - elif self.remove: - self.api_remove() - elif self.update: - self.api_update() - elif self.query: - self.check_query() - self.api_query() - elif self.extended_query: - self.check_extended_query() - self.api_extended_query() - elif self.arbitrary: - self.api_arbitrary() - else: - self.api_get_all() + # api calls + try: + if self.add: + self.api_add() + elif self.remove: + self.api_remove() + elif self.update: + self.api_update() + elif self.query: + self.check_query() + self.api_query() + elif self.extended_query: + self.check_extended_query() + self.api_extended_query() + elif self.arbitrary: + self.api_arbitrary() + else: + self.api_get_all() + except UnicodeEncodeError as exc: + self.module.fail_json(msg='Error while encoding text: {error}'.format(error=exc)) def check_query(self): where_index = self.query.find(' WHERE ') diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 0d4a282..e1265a0 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -277,7 +277,7 @@ def main(): for modification in modifications: try: api_path.update(**modification) - except LibRouterosError as e: + except (LibRouterosError, UnicodeEncodeError) as e: module.fail_json( msg='Error while modifying for .id={id}: {error}'.format( id=modification['.id'], From 6e104c962bde97ad6388df17c4e7dc27b40f214f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 24 May 2022 22:51:27 +0200 Subject: [PATCH 040/365] Extend documentation. (#96) --- README.md | 60 ++++++++++++++++++++++------------ docs/docsite/rst/api-guide.rst | 14 ++++++-- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f501c15..b1d52a9 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Please note that `community.routeros.api` module does **not** support Windows ju ## Included content - `community.routeros.api` +- `community.routeros.api_facts` +- `community.routeros.api_find_and_modify` - `community.routeros.command` - `community.routeros.facts` @@ -69,19 +71,19 @@ Example playbook: hosts: routers gather_facts: false tasks: + - name: Run a command + community.routeros.command: + commands: + - /system resource print + register: system_resource_print + - name: Print its output + ansible.builtin.debug: + var: system_resource_print.stdout_lines - # Run a command and print its output - - community.routeros.command: - commands: - - /system resource print - register: system_resource_print - - debug: - var: system_resource_print.stdout_lines - - # Retrieve facts - - community.routeros.facts: - - debug: - msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}" + - name: Retrieve facts + community.routeros.facts: + - ansible.builtin.debug: + msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}" ``` ### Connecting with HTTP/HTTPS API @@ -97,18 +99,36 @@ Example playbook: hostname: 192.168.1.1 username: admin password: test1234 + module_defaults: + group/community.routeros.api: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + tls: true + validate_certs: true + validate_cert_hostname: true + ca_path: /path/to/ca-certificate.pem tasks: - name: Get "ip address print" community.routeros.api: - hostname: "{{ hostname }}" - password: "{{ password }}" - username: "{{ username }}" - path: "ip address" - tls: true - validate_certs: true - validate_cert_hostname: true - ca_path: /path/to/ca-certificate.pem + path: ip address register: print_path + - name: Print the result + ansible.builtin.debug: + var: print_path.msg + + - name: Change IP address to 192.168.1.1 for interface bridge + community.routeros.api_find_and_modify: + path: ip address + find: + interface: bridge + values: + address: "192.168.1.1/24" + + - name: Retrieve facts + community.routeros.api_facts: + - ansible.builtin.debug: + msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}" ``` ## Contributing to this collection diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index bccdcfe..a8a9e9a 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -3,7 +3,7 @@ How to connect to RouterOS devices with the RouterOS API ======================================================== -You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. The :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. +You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. A more specific module to modify certain entries is the :ref:`community.routeros.api_find_and_modify module `. The :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. No special setup is needed; the module needs to be run on a host that can connect to the device's API. The most common case is that the module is run on ``localhost``, either by using ``hosts: localhost`` in the playbook, or by using ``delegate_to: localhost`` for the task. The following example shows how to run the equivalent of ``/ip address print``: @@ -59,7 +59,7 @@ Check out the documenation of the :ref:`community.routeros.api module ` and :ref:`community.routeros.api_facts module ` in every task, you can use the ``community.routeros.api`` module defaults group: +To avoid having to specify common parameters for all the API based modules in every task, you can use the ``community.routeros.api`` module defaults group: .. code-block:: yaml+jinja @@ -87,7 +87,15 @@ To avoid having to specify common parameters for the :ref:`community.routeros.ap community.routeros.api: path: "ip address" -Here both tasks will use the options set for the module defaults group. + - name: Change IP address to 192.168.1.1 for interface bridge + community.routeros.api_find_and_modify: + path: ip address + find: + interface: bridge + values: + address: "192.168.1.1/24" + +Here all three tasks will use the options set for the module defaults group. Setting up encryption --------------------- From 3a34bb9ba4a5a840939278db947f18955a5b3848 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 25 May 2022 06:27:08 +0200 Subject: [PATCH 041/365] Release 2.1.0. --- CHANGELOG.rst | 29 +++++++++++++++ changelogs/changelog.yaml | 36 +++++++++++++++++++ changelogs/fragments/2.1.0.yml | 1 - .../fragments/63-add-extended_query.yml | 3 -- .../fragments/68-fix-query-id-check.yml | 2 -- changelogs/fragments/83-ee.yml | 2 -- changelogs/fragments/89-quoting.yml | 2 -- changelogs/fragments/90-api-action-group.yml | 2 -- changelogs/fragments/95-api-encoding.yml | 2 -- 9 files changed, 65 insertions(+), 14 deletions(-) delete mode 100644 changelogs/fragments/2.1.0.yml delete mode 100644 changelogs/fragments/63-add-extended_query.yml delete mode 100644 changelogs/fragments/68-fix-query-id-check.yml delete mode 100644 changelogs/fragments/83-ee.yml delete mode 100644 changelogs/fragments/89-quoting.yml delete mode 100644 changelogs/fragments/90-api-action-group.yml delete mode 100644 changelogs/fragments/95-api-encoding.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 347399d..8bad8be 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,35 @@ Community RouterOS Release Notes .. contents:: Topics +v2.1.0 +====== + +Release Summary +--------------- + +Feature and bugfix release with new modules. + +Minor Changes +------------- + +- Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89). +- Prepare collection for inclusion in an Execution Environment by declaring its dependencies (https://github.com/ansible-collections/community.routeros/pull/83). +- api - add new option ``extended query`` more complex queries against RouterOS API (https://github.com/ansible-collections/community.routeros/pull/63). +- api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63). +- api* modules - allow to set an encoding other than the default ASCII for communicating with the API (https://github.com/ansible-collections/community.routeros/pull/95). + +Bugfixes +-------- + +- query - fix query function check for ``.id`` vs. ``id`` arguments to not conflict with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, https://github.com/ansible-collections/community.routeros/issues/67). +- quoting and unquoting filter plugins, api module - handle the escape sequence ``\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89). + +New Modules +----------- + +- api_facts - Collect facts from remote devices running MikroTik RouterOS using the API +- api_find_and_modify - Find and modify information using the API + v2.0.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 4fbd1db..8872b1d 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -153,3 +153,39 @@ releases: name: split namespace: null release_date: '2021-10-14' + 2.1.0: + changes: + bugfixes: + - query - fix query function check for ``.id`` vs. ``id`` arguments to not conflict + with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, + https://github.com/ansible-collections/community.routeros/issues/67). + - quoting and unquoting filter plugins, api module - handle the escape sequence + ``\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89). + minor_changes: + - Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` + to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89). + - Prepare collection for inclusion in an Execution Environment by declaring + its dependencies (https://github.com/ansible-collections/community.routeros/pull/83). + - api - add new option ``extended query`` more complex queries against RouterOS + API (https://github.com/ansible-collections/community.routeros/pull/63). + - api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63). + - api* modules - allow to set an encoding other than the default ASCII for communicating + with the API (https://github.com/ansible-collections/community.routeros/pull/95). + release_summary: Feature and bugfix release with new modules. + fragments: + - 2.1.0.yml + - 63-add-extended_query.yml + - 68-fix-query-id-check.yml + - 83-ee.yml + - 89-quoting.yml + - 90-api-action-group.yml + - 95-api-encoding.yml + modules: + - description: Collect facts from remote devices running MikroTik RouterOS using + the API + name: api_facts + namespace: '' + - description: Find and modify information using the API + name: api_find_and_modify + namespace: '' + release_date: '2022-05-25' diff --git a/changelogs/fragments/2.1.0.yml b/changelogs/fragments/2.1.0.yml deleted file mode 100644 index 50ba42f..0000000 --- a/changelogs/fragments/2.1.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature and bugfix release with new modules. diff --git a/changelogs/fragments/63-add-extended_query.yml b/changelogs/fragments/63-add-extended_query.yml deleted file mode 100644 index dc39caf..0000000 --- a/changelogs/fragments/63-add-extended_query.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - "api - add new option ``extended query`` more complex queries against RouterOS API (https://github.com/ansible-collections/community.routeros/pull/63)." - - "api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63)." diff --git a/changelogs/fragments/68-fix-query-id-check.yml b/changelogs/fragments/68-fix-query-id-check.yml deleted file mode 100644 index c5abb53..0000000 --- a/changelogs/fragments/68-fix-query-id-check.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "query - fix query function check for ``.id`` vs. ``id`` arguments to not conflict with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, https://github.com/ansible-collections/community.routeros/issues/67)." diff --git a/changelogs/fragments/83-ee.yml b/changelogs/fragments/83-ee.yml deleted file mode 100644 index 1358503..0000000 --- a/changelogs/fragments/83-ee.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - "Prepare collection for inclusion in an Execution Environment by declaring its dependencies (https://github.com/ansible-collections/community.routeros/pull/83)." diff --git a/changelogs/fragments/89-quoting.yml b/changelogs/fragments/89-quoting.yml deleted file mode 100644 index bec8340..0000000 --- a/changelogs/fragments/89-quoting.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "quoting and unquoting filter plugins, api module - handle the escape sequence ``\\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89)." diff --git a/changelogs/fragments/90-api-action-group.yml b/changelogs/fragments/90-api-action-group.yml deleted file mode 100644 index 23c748a..0000000 --- a/changelogs/fragments/90-api-action-group.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - "Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89)." diff --git a/changelogs/fragments/95-api-encoding.yml b/changelogs/fragments/95-api-encoding.yml deleted file mode 100644 index d3e0ea3..0000000 --- a/changelogs/fragments/95-api-encoding.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - "api* modules - allow to set an encoding other than the default ASCII for communicating with the API (https://github.com/ansible-collections/community.routeros/pull/95)." From b02cb44c1bc1520d1b7b912b2eb0c49c5dd54172 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 11 Jun 2022 22:06:02 +0200 Subject: [PATCH 042/365] Improve CI. (#97) --- .github/workflows/ansible-test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 65223cc..7b0d08d 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -142,7 +142,6 @@ jobs: ansible: - devel python: - - 3.8 - 3.9 - "3.10" - "3.11" From 49fb46c4a399595c8195af6cc34e66f7c01ddd21 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 29 Jun 2022 21:12:24 +0200 Subject: [PATCH 043/365] Add docs PR workflow that a) builds docs and b) show the docs diff that a PR ceates. (#99) --- .github/workflows/docs-pr.yml | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/docs-pr.yml diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml new file mode 100644 index 0000000..5c9d706 --- /dev/null +++ b/.github/workflows/docs-pr.yml @@ -0,0 +1,54 @@ +name: Collection Docs +concurrency: + group: docs-${{ github.head_ref }} + cancel-in-progress: true +on: + pull_request_target: + types: [opened, synchronize, reopened, closed] + +jobs: + build-docs: + permissions: + contents: read + name: Build Ansible Docs + uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main + with: + init-fail-on-error: true + ansible-ref: devel + + comment: + permissions: + pull-requests: write + runs-on: ubuntu-latest + needs: build-docs + name: PR comments + steps: + - name: PR comment + uses: ansible-community/github-docs-build/actions/ansible-docs-build-comment@main + with: + body-includes: '## Docs Build' + reactions: heart + action: ${{ needs.build-docs.outputs.changed != 'true' && 'remove' || '' }} + on-closed-body: | + ## Docs Build 📝 + + This PR is closed and any previously published docsite has been unpublished. + on-merged-body: | + ## Docs Build 📝 + + Thank you for contribution!✨ + + This PR has been merged and your docs changes will be incorporated when they are next published. + body: | + ## Docs Build 📝 + + Thank you for contribution!✨ + + The docsite for **this PR** is available for download as an artifact from this run: + ${{ needs.build-docs.outputs.artifact-url }} + + File changes: + + ${{ needs.build-docs.outputs.diff-files-rendered }} + + ${{ needs.build-docs.outputs.diff-rendered }} From 7973f58661ed8fd58d02c443872fce3f9d910edf Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 18 Jul 2022 23:16:54 +0200 Subject: [PATCH 044/365] Move licenses to LICENSES/, use SPDX-License-Identifier, mention all licenses in galaxy.yml, add missing license file (#101) * Add SPDX license identifiers, mention all licenses in galaxy.yml. * Add default copyright headers. * Adjust remaining/missing entries. * Fix/add more copyright statements. * Add sanity test. * Add changelog. * Add missing license file. * Remove colon after 'Copyright'. * Avoid colon after 'Copyright' in lint script. --- .github/patchback.yml | 4 + .github/workflows/ansible-test.yml | 5 + .github/workflows/docs-pr.yml | 5 + .github/workflows/ee.yml | 4 + .github/workflows/extra-tests.yml | 5 + .github/workflows/import-galaxy.yml | 5 + .gitignore | 4 + LICENSES/BSD-2-Clause.txt | 8 ++ LICENSES/GPL-3.0-or-later.txt | 1 + README.md | 6 + changelogs/config.yaml | 5 + changelogs/fragments/101-licenses.yml | 4 + codecov.yml | 5 + docs/docsite/extra-docs.yml | 4 + docs/docsite/links.yml | 4 + docs/docsite/rst/api-guide.rst | 5 + docs/docsite/rst/quoting.rst | 5 + docs/docsite/rst/ssh-guide.rst | 5 + galaxy.yml | 9 +- meta/ee-requirements.txt | 4 + meta/execution-environment.yml | 4 + meta/runtime.yml | 4 + plugins/cliconf/routeros.py | 22 +--- plugins/doc_fragments/api.py | 3 +- plugins/filter/join.yml | 5 + plugins/filter/list_to_dict.yml | 5 + plugins/filter/quote_argument.yml | 5 + plugins/filter/quote_argument_value.yml | 5 + plugins/filter/quoting.py | 5 +- plugins/filter/split.yml | 5 + plugins/module_utils/__init__.py | 0 plugins/module_utils/_api_data.py | 5 +- plugins/module_utils/api.py | 7 +- plugins/module_utils/quoting.py | 5 +- plugins/module_utils/routeros.py | 30 +---- plugins/modules/api.py | 3 +- plugins/modules/api_facts.py | 9 +- plugins/modules/api_find_and_modify.py | 3 +- plugins/modules/command.py | 4 +- plugins/modules/facts.py | 4 +- plugins/terminal/routeros.py | 22 +--- tests/config.yml | 4 + tests/ee/all.yml | 5 + tests/ee/roles/filter_quoting/aliases | 4 + tests/ee/roles/filter_quoting/tasks/main.yml | 4 + tests/ee/roles/smoke/tasks/main.yml | 4 + .../targets/filter_quoting/aliases | 4 + .../targets/filter_quoting/tasks/main.yml | 4 + tests/requirements.yml | 5 + tests/sanity/extra/extra-docs.py | 3 +- tests/sanity/extra/licenses.json | 4 + tests/sanity/extra/licenses.py | 111 ++++++++++++++++++ tests/sanity/extra/no-unwanted-files.py | 3 +- tests/unit/compat/builtins.py | 19 +-- tests/unit/compat/mock.py | 19 +-- tests/unit/compat/unittest.py | 19 +-- .../plugins/module_utils/test__api_data.py | 5 +- .../unit/plugins/module_utils/test_quoting.py | 5 +- tests/unit/plugins/modules/__init__.py | 0 tests/unit/plugins/modules/fake_api.py | 17 +-- .../unit/plugins/modules/fixtures/__init__.py | 0 tests/unit/plugins/modules/routeros_module.py | 19 +-- tests/unit/plugins/modules/test_api.py | 17 +-- tests/unit/plugins/modules/test_api_facts.py | 17 +-- .../modules/test_api_find_and_modify.py | 17 +-- tests/unit/plugins/modules/test_command.py | 19 +-- tests/unit/plugins/modules/test_facts.py | 17 +-- tests/unit/plugins/modules/utils.py | 4 + tests/unit/requirements.txt | 4 + 69 files changed, 367 insertions(+), 238 deletions(-) create mode 100644 LICENSES/BSD-2-Clause.txt create mode 120000 LICENSES/GPL-3.0-or-later.txt create mode 100644 changelogs/fragments/101-licenses.yml delete mode 100644 plugins/module_utils/__init__.py create mode 100644 tests/sanity/extra/licenses.json create mode 100755 tests/sanity/extra/licenses.py delete mode 100644 tests/unit/plugins/modules/__init__.py delete mode 100644 tests/unit/plugins/modules/fixtures/__init__.py diff --git a/.github/patchback.yml b/.github/patchback.yml index 33ad6e8..5ee7812 100644 --- a/.github/patchback.yml +++ b/.github/patchback.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + backport_branch_prefix: patchback/backports/ backport_label_prefix: backport- target_branch_prefix: stable- diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 7b0d08d..1343492 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + name: CI on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 5c9d706..ef44a68 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + name: Collection Docs concurrency: group: docs-${{ github.head_ref }} diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 25600dc..8d005f4 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + name: execution environment on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 5f29828..a4fe4b5 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + name: extra-tests on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index c7cb607..47b0db3 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + name: import-galaxy on: # Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests diff --git a/.gitignore b/.gitignore index 740c811..8e398ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + /tests/output/ /changelogs/.plugin-cache.yaml diff --git a/LICENSES/BSD-2-Clause.txt b/LICENSES/BSD-2-Clause.txt new file mode 100644 index 0000000..6810e04 --- /dev/null +++ b/LICENSES/BSD-2-Clause.txt @@ -0,0 +1,8 @@ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 120000 index 0000000..012065c --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1 @@ +../COPYING \ No newline at end of file diff --git a/README.md b/README.md index b1d52a9..0f1b363 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ + + # 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) diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 8f014ed..70a1f67 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + changelog_filename_template: ../CHANGELOG.rst changelog_filename_version_depth: 0 changes_file: changelog.yaml diff --git a/changelogs/fragments/101-licenses.yml b/changelogs/fragments/101-licenses.yml new file mode 100644 index 0000000..e54f8a2 --- /dev/null +++ b/changelogs/fragments/101-licenses.yml @@ -0,0 +1,4 @@ +minor_changes: + - "All software licenses are now in the ``LICENSES/`` directory of the collection root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101)." +bugfixes: + - "Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils (https://github.com/ansible-collections/community.routeros/pull/101)." diff --git a/codecov.yml b/codecov.yml index 724e063..3b2f9ed 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,2 +1,7 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + fixes: - "ansible_collections/community/routeros/::" diff --git a/docs/docsite/extra-docs.yml b/docs/docsite/extra-docs.yml index 385bd7e..6091591 100644 --- a/docs/docsite/extra-docs.yml +++ b/docs/docsite/extra-docs.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + sections: - title: Guides toctree: diff --git a/docs/docsite/links.yml b/docs/docsite/links.yml index d95c205..9da799e 100644 --- a/docs/docsite/links.yml +++ b/docs/docsite/links.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + edit_on_github: repository: ansible-collections/community.routeros branch: main diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index a8a9e9a..a3bb574 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -1,3 +1,8 @@ +.. + Copyright (c) Ansible Project + GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) + SPDX-License-Identifier: GPL-3.0-or-later + .. _ansible_collections.community.routeros.docsite.api-guide: How to connect to RouterOS devices with the RouterOS API diff --git a/docs/docsite/rst/quoting.rst b/docs/docsite/rst/quoting.rst index f17a861..785c7f8 100644 --- a/docs/docsite/rst/quoting.rst +++ b/docs/docsite/rst/quoting.rst @@ -1,3 +1,8 @@ +.. + Copyright (c) Ansible Project + GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) + SPDX-License-Identifier: GPL-3.0-or-later + .. _ansible_collections.community.routeros.docsite.quoting: How to quote and unquote commands and arguments diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index 4c59d5c..bdbdbfe 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -1,3 +1,8 @@ +.. + Copyright (c) Ansible Project + GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) + SPDX-License-Identifier: GPL-3.0-or-later + .. _ansible_collections.community.routeros.docsite.ssh-guide: How to connect to RouterOS devices with SSH diff --git a/galaxy.yml b/galaxy.yml index bae2ab9..2ba0a85 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + # See https://docs.ansible.com/ansible/latest/dev_guide/collections_galaxy_meta.html namespace: community @@ -9,7 +14,9 @@ authors: - Nikolay Dachev (github.com/NikolayDachev) - Felix Fontein (github.com/felixfontein) description: Modules for MikroTik RouterOS -license_file: COPYING +license: + - GPL-3.0-or-later +#license_file: COPYING tags: - network - mikrotik diff --git a/meta/ee-requirements.txt b/meta/ee-requirements.txt index f3d520b..a36140c 100644 --- a/meta/ee-requirements.txt +++ b/meta/ee-requirements.txt @@ -1 +1,5 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + librouteros diff --git a/meta/execution-environment.yml b/meta/execution-environment.yml index c899493..ac7ebac 100644 --- a/meta/execution-environment.yml +++ b/meta/execution-environment.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + version: 1 dependencies: python: meta/ee-requirements.txt diff --git a/meta/runtime.yml b/meta/runtime.yml index 6a8be34..6668842 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + requires_ansible: '>=2.9.10' action_groups: api: diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py index f46b3a0..6a5cb2c 100644 --- a/plugins/cliconf/routeros.py +++ b/plugins/cliconf/routeros.py @@ -1,21 +1,7 @@ -# -# (c) 2017 Red Hat Inc. -# -# 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 . -# +# Copyright (c) 2017 Red Hat Inc. +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index 6995c5c..ddbea6d 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2020, Nikolay Dachev +# Copyright (c) 2020, Nikolay Dachev # GNU General Public License v3.0+ https://www.gnu.org/licenses/gpl-3.0.txt +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/filter/join.yml b/plugins/filter/join.yml index 1642ef1..9ff8a50 100644 --- a/plugins/filter/join.yml +++ b/plugins/filter/join.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + DOCUMENTATION: name: join short_description: Join a list of arguments to a command diff --git a/plugins/filter/list_to_dict.yml b/plugins/filter/list_to_dict.yml index bfac7c4..920414c 100644 --- a/plugins/filter/list_to_dict.yml +++ b/plugins/filter/list_to_dict.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + DOCUMENTATION: name: list_to_dict short_description: Convert a list of arguments to a dictionary diff --git a/plugins/filter/quote_argument.yml b/plugins/filter/quote_argument.yml index 4389fc5..26a1f04 100644 --- a/plugins/filter/quote_argument.yml +++ b/plugins/filter/quote_argument.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + DOCUMENTATION: name: quote_argument short_description: Quote an argument diff --git a/plugins/filter/quote_argument_value.yml b/plugins/filter/quote_argument_value.yml index 65f50d0..839895b 100644 --- a/plugins/filter/quote_argument_value.yml +++ b/plugins/filter/quote_argument_value.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + DOCUMENTATION: name: quote_argument_value short_description: Quote an argument value diff --git a/plugins/filter/quoting.py b/plugins/filter/quoting.py index aabb421..3985d55 100644 --- a/plugins/filter/quoting.py +++ b/plugins/filter/quoting.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2021, Felix Fontein -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2021, Felix Fontein +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/plugins/filter/split.yml b/plugins/filter/split.yml index d56b820..5fc4b30 100644 --- a/plugins/filter/split.yml +++ b/plugins/filter/split.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + DOCUMENTATION: name: split short_description: Split a command into arguments diff --git a/plugins/module_utils/__init__.py b/plugins/module_utils/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ab771d0..1b8bafa 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2022, Felix Fontein (@felixfontein) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # The data inside here is private to this collection. If you use this from outside the collection, # you are on your own. There can be random changes to its format even in bugfix releases! diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 7150dcc..f4060f1 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2022, Felix Fontein (@felixfontein) -# Copyright: (c) 2020, Nikolay Dachev -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# Copyright (c) 2020, Nikolay Dachev +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/plugins/module_utils/quoting.py b/plugins/module_utils/quoting.py index 5524de4..4b70989 100644 --- a/plugins/module_utils/quoting.py +++ b/plugins/module_utils/quoting.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2021, Felix Fontein (@felixfontein) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/plugins/module_utils/routeros.py b/plugins/module_utils/routeros.py index e0488b2..3efd524 100644 --- a/plugins/module_utils/routeros.py +++ b/plugins/module_utils/routeros.py @@ -1,30 +1,6 @@ -# This code is part of Ansible, but is an independent component. -# This particular file snippet, and this file snippet only, is BSD licensed. -# Modules you write using this snippet, which is embedded dynamically by Ansible -# still belong to the author of the module, and may assign their own license -# to the complete work. -# -# (c) 2016 Red Hat Inc. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# +# Copyright (c) 2016 Red Hat Inc. +# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause) +# SPDX-License-Identifier: BSD-2-Clause from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/plugins/modules/api.py b/plugins/modules/api.py index ddd026c..9ead0f3 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -1,8 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# Copyright: (c) 2020, Nikolay Dachev +# Copyright (c) 2020, Nikolay Dachev # GNU General Public License v3.0+ https://www.gnu.org/licenses/gpl-3.0.txt +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index b5d0e17..7cc2aa3 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -1,9 +1,10 @@ #!/usr/bin/python -# Copyright: (c) 2022, Felix Fontein -# Copyright: (c) 2020, Nikolay Dachev -# Copyright: (c) 2018, Egor Zaitsev (@heuels) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2022, Felix Fontein +# Copyright (c) 2020, Nikolay Dachev +# Copyright (c) 2018, Egor Zaitsev (@heuels) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index e1265a0..099d739 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -1,8 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# Copyright: (c) 2022, Felix Fontein +# Copyright (c) 2022, Felix Fontein # GNU General Public License v3.0+ https://www.gnu.org/licenses/gpl-3.0.txt +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/modules/command.py b/plugins/modules/command.py index f292792..c96e153 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -1,6 +1,8 @@ #!/usr/bin/python -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 3b423ca..383f940 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -1,6 +1,8 @@ #!/usr/bin/python -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/terminal/routeros.py b/plugins/terminal/routeros.py index 8648ff5..a2646e3 100644 --- a/plugins/terminal/routeros.py +++ b/plugins/terminal/routeros.py @@ -1,21 +1,7 @@ -# -# (c) 2016 Red Hat Inc. -# -# 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 . -# +# Copyright (c) 2016 Red Hat Inc. +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/tests/config.yml b/tests/config.yml index ba0238e..38590f2 100644 --- a/tests/config.yml +++ b/tests/config.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + # See template for more information: # https://github.com/ansible/ansible/blob/devel/test/lib/ansible_test/config/config.yml modules: diff --git a/tests/ee/all.yml b/tests/ee/all.yml index 7593912..26f198b 100644 --- a/tests/ee/all.yml +++ b/tests/ee/all.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + - hosts: localhost tasks: - name: Find all roles diff --git a/tests/ee/roles/filter_quoting/aliases b/tests/ee/roles/filter_quoting/aliases index 54ea5a3..ddba818 100644 --- a/tests/ee/roles/filter_quoting/aliases +++ b/tests/ee/roles/filter_quoting/aliases @@ -1,2 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + shippable/posix/group1 skip/python2.6 diff --git a/tests/ee/roles/filter_quoting/tasks/main.yml b/tests/ee/roles/filter_quoting/tasks/main.yml index bebed37..e7a2d29 100644 --- a/tests/ee/roles/filter_quoting/tasks/main.yml +++ b/tests/ee/roles/filter_quoting/tasks/main.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + - name: "Test split filter" assert: that: diff --git a/tests/ee/roles/smoke/tasks/main.yml b/tests/ee/roles/smoke/tasks/main.yml index 33adbff..072f4cc 100644 --- a/tests/ee/roles/smoke/tasks/main.yml +++ b/tests/ee/roles/smoke/tasks/main.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + - name: Run api module community.routeros.api: username: foo diff --git a/tests/integration/targets/filter_quoting/aliases b/tests/integration/targets/filter_quoting/aliases index 54ea5a3..ddba818 100644 --- a/tests/integration/targets/filter_quoting/aliases +++ b/tests/integration/targets/filter_quoting/aliases @@ -1,2 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + shippable/posix/group1 skip/python2.6 diff --git a/tests/integration/targets/filter_quoting/tasks/main.yml b/tests/integration/targets/filter_quoting/tasks/main.yml index bebed37..e7a2d29 100644 --- a/tests/integration/targets/filter_quoting/tasks/main.yml +++ b/tests/integration/targets/filter_quoting/tasks/main.yml @@ -1,4 +1,8 @@ --- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + - name: "Test split filter" assert: that: diff --git a/tests/requirements.yml b/tests/requirements.yml index a218740..0186af5 100644 --- a/tests/requirements.yml +++ b/tests/requirements.yml @@ -1,3 +1,8 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + integration_tests_dependencies: - ansible.netcommon unit_tests_dependencies: diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py index f2746e5..6731049 100755 --- a/tests/sanity/extra/extra-docs.py +++ b/tests/sanity/extra/extra-docs.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later """Check extra collection docs with antsibull-docs.""" from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/tests/sanity/extra/licenses.json b/tests/sanity/extra/licenses.json new file mode 100644 index 0000000..50e47ca --- /dev/null +++ b/tests/sanity/extra/licenses.json @@ -0,0 +1,4 @@ +{ + "include_symlinks": false, + "output": "path-message" +} diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py new file mode 100755 index 0000000..fe02989 --- /dev/null +++ b/tests/sanity/extra/licenses.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# Copyright (c) 2022, Felix Fontein +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +"""Prevent files without a correct license identifier from being added to the source tree.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import glob +import sys + + +def format_license_list(licenses): + if not licenses: + return '(empty)' + return ', '.join(['"%s"' % license for license in licenses]) + + +def find_licenses(filename, relax=False): + spdx_license_identifiers = [] + other_license_identifiers = [] + has_copyright = False + with open(filename, 'r') as f: + for line in f: + line = line.rstrip() + if 'Copyright ' in line: + has_copyright = True + if 'Copyright: ' in line: + print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, )) + idx = line.find('SPDX-License-Identifier: ') + if idx >= 0: + spdx_license_identifiers.append(line[idx + len('SPDX-License-Identifier: '):]) + if 'GNU General Public License' in line: + if 'v3.0+' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'version 3 or later' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'Simplified BSD License' in line: + other_license_identifiers.append('BSD-2-Clause') + if 'Apache License 2.0' in line: + other_license_identifiers.append('Apache-2.0') + if 'PSF License' in line or 'Python-2.0' in line: + other_license_identifiers.append('PSF-2.0') + if 'MIT License' in line: + other_license_identifiers.append('MIT') + if len(set(spdx_license_identifiers)) < len(spdx_license_identifiers): + print('%s: found identical SPDX-License-Identifier values' % (filename, )) + if other_license_identifiers and set(other_license_identifiers) != set(spdx_license_identifiers): + print('%s: SPDX-License-Identifier yielded the license list %s, while manual guessing yielded the license list %s' % ( + filename, format_license_list(spdx_license_identifiers), format_license_list(other_license_identifiers))) + if not has_copyright and not relax: + print('%s: found no copyright notice' % (filename, )) + return sorted(spdx_license_identifiers) + + +def main(): + """Main entry point.""" + paths = sys.argv[1:] or sys.stdin.read().splitlines() + + no_comments_allowed = [ + 'changelogs/fragments/*.yml', + 'tests/sanity/extra/*.json', + 'tests/sanity/ignore-2.*.txt', + 'tests/unit/plugins/modules/fixtures/*', + 'tests/unit/plugins/modules/fixtures/facts/*', + 'LICENSES/*.txt', + 'COPYING', + ] + + empty_allowed = [ + '.keep', + '__init__.py', + ] + + ignore_paths = [ + 'CHANGELOG.rst', + 'changelogs/changelog.yaml', + 'tests/sanity/extra/licenses.py', # The strings in find_licenses() confuse this code :-) + '.ansible-test-timeout.json', + ] + + no_comments_allowed = [fn for pattern in no_comments_allowed for fn in glob.glob(pattern)] + ignore_paths = [fn for pattern in ignore_paths for fn in glob.glob(pattern)] + + valid_licenses = [license_file[len('LICENSES/'):-len('.txt')] for license_file in glob.glob('LICENSES/*.txt')] + + for path in paths: + if path.startswith('./'): + path = path[2:] + if path in ignore_paths or path.startswith('tests/output/'): + continue + if os.path.basename(path) in empty_allowed: + if os.stat(path).st_size == 0: + continue + valid_licenses_for_path = valid_licenses + if path.startswith('plugins/') and not path.startswith(('plugins/modules/', 'plugins/module_utils/')): + valid_licenses_for_path = [license for license in valid_licenses if license == 'GPL-3.0-or-later'] + licenses = find_licenses(path, relax=path in no_comments_allowed) + if not licenses: + if path not in no_comments_allowed: + print('%s: must have at least one license' % (path, )) + else: + for license in licenses: + if license not in valid_licenses_for_path: + print('%s: found not allowed license "%s", must be one of %s' % ( + path, license, format_license_list(valid_licenses_for_path))) + + +if __name__ == '__main__': + main() diff --git a/tests/sanity/extra/no-unwanted-files.py b/tests/sanity/extra/no-unwanted-files.py index 4522f77..b39df83 100755 --- a/tests/sanity/extra/no-unwanted-files.py +++ b/tests/sanity/extra/no-unwanted-files.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later """Prevent unwanted files from being added to the source tree.""" from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/tests/unit/compat/builtins.py b/tests/unit/compat/builtins.py index f60ee67..b0cc618 100644 --- a/tests/unit/compat/builtins.py +++ b/tests/unit/compat/builtins.py @@ -1,19 +1,6 @@ -# (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 . +# Copyright (c) 2014, Toshio Kuratomi +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/compat/mock.py b/tests/unit/compat/mock.py index 0972cd2..f8f565d 100644 --- a/tests/unit/compat/mock.py +++ b/tests/unit/compat/mock.py @@ -1,19 +1,6 @@ -# (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 . +# Copyright (c) 2014, Toshio Kuratomi +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/compat/unittest.py b/tests/unit/compat/unittest.py index 98f08ad..1872e58 100644 --- a/tests/unit/compat/unittest.py +++ b/tests/unit/compat/unittest.py @@ -1,19 +1,6 @@ -# (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 . +# Copyright (c) 2014, Toshio Kuratomi +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 5053ca9..67b5b1b 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2021, Felix Fontein (@felixfontein) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/tests/unit/plugins/module_utils/test_quoting.py b/tests/unit/plugins/module_utils/test_quoting.py index fe13b66..6d29d50 100644 --- a/tests/unit/plugins/module_utils/test_quoting.py +++ b/tests/unit/plugins/module_utils/test_quoting.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright: (c) 2021, Felix Fontein (@felixfontein) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# Copyright (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/tests/unit/plugins/modules/__init__.py b/tests/unit/plugins/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index edfa28a..95d59ba 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -1,17 +1,6 @@ -# 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 . +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/fixtures/__init__.py b/tests/unit/plugins/modules/fixtures/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/unit/plugins/modules/routeros_module.py b/tests/unit/plugins/modules/routeros_module.py index 9cad18e..0ec44f7 100644 --- a/tests/unit/plugins/modules/routeros_module.py +++ b/tests/unit/plugins/modules/routeros_module.py @@ -1,19 +1,6 @@ -# (c) 2016 Red Hat Inc. -# -# 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 . +# Copyright (c) 2016 Red Hat Inc. +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index 94982ac..be63393 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -1,17 +1,6 @@ -# 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 . +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py index 0c41806..8c34be2 100644 --- a/tests/unit/plugins/modules/test_api_facts.py +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -1,17 +1,6 @@ -# 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 . +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index 5655d02..e1b1645 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -1,17 +1,6 @@ -# 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 . +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/test_command.py b/tests/unit/plugins/modules/test_command.py index 0bb4f07..3fc5865 100644 --- a/tests/unit/plugins/modules/test_command.py +++ b/tests/unit/plugins/modules/test_command.py @@ -1,19 +1,6 @@ -# (c) 2016 Red Hat Inc. -# -# 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 . +# Copyright (c) 2016 Red Hat Inc. +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/test_facts.py b/tests/unit/plugins/modules/test_facts.py index 9552047..322fdda 100644 --- a/tests/unit/plugins/modules/test_facts.py +++ b/tests/unit/plugins/modules/test_facts.py @@ -1,17 +1,6 @@ -# 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 . +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) diff --git a/tests/unit/plugins/modules/utils.py b/tests/unit/plugins/modules/utils.py index 0468b68..419eef1 100644 --- a/tests/unit/plugins/modules/utils.py +++ b/tests/unit/plugins/modules/utils.py @@ -1,3 +1,7 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + from __future__ import absolute_import, division, print_function __metaclass__ = type diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index 0b66e0a..479f2fc 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -1,2 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + unittest2 ; python_version <= '2.6' ordereddict ; python_version <= '2.6' From 1abaa8e7ca387ce7cefe89266b5fe5fa84ee2402 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 20 Jul 2022 23:05:15 +0200 Subject: [PATCH 045/365] Improve sanity test, improve README. (#102) --- README.md | 8 ++++++-- tests/sanity/extra/licenses.py | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0f1b363..b6ec82f 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,10 @@ We plan to regularly release minor and patch versions, whenever new features are ## Licensing -GNU General Public License v3.0 or later. +This collection is primarily licensed and distributed as a whole under the GNU General Public License v3.0 or later. -See [COPYING](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. +See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.routeros/blob/main/COPYING) for the full text. + +Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.routeros/blob/main/LICENSES/BSD-2-Clause.txt). + +Most files in the collection that are not automatically generated have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s). diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py index fe02989..4708822 100755 --- a/tests/sanity/extra/licenses.py +++ b/tests/sanity/extra/licenses.py @@ -21,7 +21,7 @@ def find_licenses(filename, relax=False): spdx_license_identifiers = [] other_license_identifiers = [] has_copyright = False - with open(filename, 'r') as f: + with open(filename, 'r', encoding='utf-8') as f: for line in f: line = line.rstrip() if 'Copyright ' in line: @@ -58,6 +58,7 @@ def main(): """Main entry point.""" paths = sys.argv[1:] or sys.stdin.read().splitlines() + # The following paths are allowed to have no license identifier no_comments_allowed = [ 'changelogs/fragments/*.yml', 'tests/sanity/extra/*.json', @@ -68,11 +69,13 @@ def main(): 'COPYING', ] + # Files of this name are allowed to be empty empty_allowed = [ '.keep', '__init__.py', ] + # These files are completely ignored ignore_paths = [ 'CHANGELOG.rst', 'changelogs/changelog.yaml', From 2911710f1b9134592efcefa099e10f838c24afef Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 31 Jul 2022 22:06:19 +0200 Subject: [PATCH 046/365] Add api_info and api_modify modules (#91) * Add api_info and api_modify modules. * Add documentation, and cross-references for the modules. * Bump version added for new modules. * Ignore dynamic entries. Allow _info module to return them. * Document behavior for dynamic entries. * Update license headers. * Add disclaimer. * Improve formulation. * Auto-generate path list in DOCUMENTATION. * Add test to make sure lists have been generated automatically. --- README.md | 2 + docs/docsite/rst/api-guide.rst | 2 +- meta/runtime.yml | 2 + plugins/module_utils/_api_data.py | 5 +- plugins/modules/api.py | 7 + plugins/modules/api_facts.py | 3 + plugins/modules/api_find_and_modify.py | 5 + plugins/modules/api_info.py | 290 ++++ plugins/modules/api_modify.py | 918 ++++++++++ tests/sanity/extra/update-docs.json | 8 + tests/sanity/extra/update-docs.py | 22 + tests/sanity/ignore-2.10.txt | 6 + tests/sanity/ignore-2.11.txt | 6 + tests/sanity/ignore-2.12.txt | 1 + tests/sanity/ignore-2.13.txt | 1 + tests/sanity/ignore-2.14.txt | 1 + tests/sanity/ignore-2.9.txt | 6 + tests/unit/plugins/modules/fake_api.py | 4 +- tests/unit/plugins/modules/test_api_info.py | 408 +++++ tests/unit/plugins/modules/test_api_modify.py | 1540 +++++++++++++++++ update-docs.py | 46 + 21 files changed, 3277 insertions(+), 6 deletions(-) create mode 100644 plugins/modules/api_info.py create mode 100644 plugins/modules/api_modify.py create mode 100644 tests/sanity/extra/update-docs.json create mode 100644 tests/sanity/extra/update-docs.py create mode 100644 tests/sanity/ignore-2.10.txt create mode 100644 tests/sanity/ignore-2.11.txt create mode 100644 tests/sanity/ignore-2.12.txt create mode 100644 tests/sanity/ignore-2.13.txt create mode 100644 tests/sanity/ignore-2.14.txt create mode 100644 tests/sanity/ignore-2.9.txt create mode 100644 tests/unit/plugins/modules/test_api_info.py create mode 100644 tests/unit/plugins/modules/test_api_modify.py create mode 100755 update-docs.py diff --git a/README.md b/README.md index b6ec82f..f198a88 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ Please note that `community.routeros.api` module does **not** support Windows ju - `community.routeros.api` - `community.routeros.api_facts` - `community.routeros.api_find_and_modify` +- `community.routeros.api_info` +- `community.routeros.api_modify` - `community.routeros.command` - `community.routeros.facts` diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index a3bb574..a96d84c 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -8,7 +8,7 @@ How to connect to RouterOS devices with the RouterOS API ======================================================== -You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. A more specific module to modify certain entries is the :ref:`community.routeros.api_find_and_modify module `. The :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. +You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. More specific module to modify certain entries are the :ref:`community.routeros.api_modify ` and :ref:`community.routeros.api_find_and_modify ` modules. The :ref:`community.routeros.api_info module ` allows to retrieve information on specific predefined paths that can be used as input for the ``community.routeros.api_modify`` module, and the :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. No special setup is needed; the module needs to be run on a host that can connect to the device's API. The most common case is that the module is run on ``localhost``, either by using ``hosts: localhost`` in the playbook, or by using ``delegate_to: localhost`` for the task. The following example shows how to run the equivalent of ``/ip address print``: diff --git a/meta/runtime.yml b/meta/runtime.yml index 6668842..c9cdbbf 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -9,3 +9,5 @@ action_groups: - api - api_facts - api_find_and_modify + - api_info + - api_modify diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 1b8bafa..7951fed 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -61,10 +61,7 @@ class KeyInfo(object): def split_path(path): - parts = path.split() - if len(parts) == 1 and parts[0] == '': - parts = [] - return parts + return path.split() def join_path(path): diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 9ead0f3..3ba80d2 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -19,6 +19,9 @@ description: notes: - I(add), I(remove), I(update), I(cmd) and I(query) are mutually exclusive. - I(check_mode) is not supported. + - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules + for more specific modifications, and the M(community.routeros.api_info) module for a more controlled + way of returning all entries for a path. extends_documentation_fragment: - community.routeros.api options: @@ -133,6 +136,10 @@ options: seealso: - ref: ansible_collections.community.routeros.docsite.quoting description: How to quote and unquote commands and arguments + - module: community.routeros.api_facts + - module: community.routeros.api_find_and_modify + - module: community.routeros.api_info + - module: community.routeros.api_modify ''' EXAMPLES = ''' diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 7cc2aa3..7209f2a 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -44,6 +44,9 @@ options: seealso: - module: community.routeros.facts - module: community.routeros.api + - module: community.routeros.api_find_and_modify + - module: community.routeros.api_info + - module: community.routeros.api_modify ''' EXAMPLES = """ diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 099d739..a3b61f0 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -17,6 +17,8 @@ short_description: Find and modify information using the API version_added: 2.1.0 description: - Allows to find entries for a path by conditions and modify the values of these entries. + - Use the M(community.routeros.api_find_and_modify) module to set all entries of a path to specific values, + or change multiple entries in different ways in one step. notes: - "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that there are at least N such values, you can use I(require_matches_min=N) together with I(allow_no_matches=true). @@ -65,6 +67,9 @@ options: type: bool seealso: - module: community.routeros.api + - module: community.routeros.api_facts + - module: community.routeros.api_modify + - module: community.routeros.api_info ''' EXAMPLES = ''' diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py new file mode 100644 index 0000000..2a15bc6 --- /dev/null +++ b/plugins/modules/api_info.py @@ -0,0 +1,290 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: api_info +author: + - "Felix Fontein (@felixfontein)" +short_description: Retrieve information from API +version_added: 2.2.0 +description: + - Allows to retrieve information for a path using the API. + - This can be used to backup a path to restore it with the M(community.routeros.api_modify) module. + - Entries are normalized, and dynamic entries are not returned. Use the I(handle_disabled) and + I(hide_defaults) options to control normalization, the I(include_dynamic) option to also return + dynamic entries, and use I(unfiltered) to return all fields including counters. + - B(Note) that this module is still heavily in development, and only supports B(some) paths. + If you want to support new paths, or think you found problems with existing paths, please first + L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). +notes: + - Supports I(check_mode). +extends_documentation_fragment: + - community.routeros.api +options: + path: + description: + - Path to query. + - An example value is C(ip address). This is equivalent to running C(/ip address print) in the RouterOS CLI. + required: true + type: str + choices: + # BEGIN PATH LIST + - caps-man aaa + - certificate settings + - interface bridge port + - interface bridge port-controller + - interface bridge port-extender + - interface bridge settings + - interface detect-internet + - interface ethernet + - interface ethernet switch + - interface ethernet switch port + - interface l2tp-server server + - interface ovpn-server server + - interface pptp-server server + - interface sstp-server server + - interface wireless align + - interface wireless cap + - interface wireless sniffer + - interface wireless snooper + - ip accounting + - ip accounting web-access + - ip address + - ip cloud + - ip cloud advanced + - ip dhcp-client + - ip dhcp-client option + - ip dhcp-server + - ip dhcp-server config + - ip dhcp-server lease + - ip dhcp-server network + - ip dns + - ip dns static + - ip firewall address-list + - ip firewall connection tracking + - ip firewall filter + - ip firewall nat + - ip firewall service-port + - ip hotspot service-port + - ip ipsec settings + - ip neighbor discovery-settings + - ip pool + - ip proxy + - ip service + - ip settings + - ip smb + - ip socks + - ip ssh + - ip tftp settings + - ip traffic-flow + - ip traffic-flow ipfix + - ip upnp + - ipv6 dhcp-client + - ipv6 firewall address-list + - ipv6 firewall filter + - ipv6 nd prefix default + - ipv6 settings + - mpls + - mpls ldp + - port firmware + - ppp aaa + - queue interface + - radius incoming + - routing bgp instance + - routing mme + - routing rip + - routing ripng + - snmp + - system clock + - system clock manual + - system identity + - system leds settings + - system note + - system ntp client + - system package update + - system routerboard settings + - system upgrade mirror + - system watchdog + - tool bandwidth-server + - tool e-mail + - tool graphing + - tool mac-server + - tool mac-server mac-winbox + - tool mac-server ping + - tool romon + - tool sms + - tool sniffer + - tool traffic-generator + - user aaa + - user group + # END PATH LIST + unfiltered: + description: + - Whether to output all fields, and not just the ones supported as input for M(community.routeros.api_modify). + - Unfiltered output can contain counters and other state information. + type: bool + default: false + handle_disabled: + description: + - How to handle unset values. + - C(exclamation) prepends the keys with C(!) in the output with value C(null). + - C(null-value) uses the regular key with value C(null). + - C(omit) omits these values from the result. + type: str + choices: + - exclamation + - null-value + - omit + default: exclamation + hide_defaults: + description: + - Whether to hide default values. + type: bool + default: true + include_dynamic: + description: + - Whether to include dynamic values. + - By default, they are not returned, and the C(dynamic) keys are omitted. + - If set to C(true), they are returned as well, and the C(dynamic) keys are returned as well. + type: bool + default: false +seealso: + - module: community.routeros.api + - module: community.routeros.api_facts + - module: community.routeros.api_find_and_modify + - module: community.routeros.api_modify +''' + +EXAMPLES = ''' +--- +- name: Get IP addresses + community.routeros.api_info: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: ip address + register: ip_addresses + +- name: Print data for IP addresses + ansible.builtin.debug: + var: ip_addresses.result +''' + +RETURN = ''' +--- +result: + description: A list of all elements for the current path. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: always +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils.api import ( + api_argument_spec, + check_has_library, + create_api, +) + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( + PATHS, + join_path, + split_path, +) + +try: + from librouteros.exceptions import LibRouterosError +except Exception: + # Handled in api module_utils + pass + + +def compose_api_path(api, path): + api_path = api.path() + for p in path: + api_path = api_path.join(p) + return api_path + + +def main(): + module_args = dict( + path=dict(type='str', required=True, choices=sorted([join_path(path) for path in PATHS if PATHS[path].fully_understood])), + unfiltered=dict(type='bool', default=False), + handle_disabled=dict(type='str', choices=['exclamation', 'null-value', 'omit'], default='exclamation'), + hide_defaults=dict(type='bool', default=True), + include_dynamic=dict(type='bool', default=False), + ) + module_args.update(api_argument_spec()) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + + check_has_library(module) + api = create_api(module) + + path = split_path(module.params['path']) + path_info = PATHS.get(tuple(path)) + if path_info is None: + module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) + + handle_disabled = module.params['handle_disabled'] + hide_defaults = module.params['hide_defaults'] + include_dynamic = module.params['include_dynamic'] + try: + api_path = compose_api_path(api, path) + + result = [] + unfiltered = module.params['unfiltered'] + for entry in api_path: + if not include_dynamic: + if entry.get('dynamic', False): + continue + if not unfiltered: + for k in list(entry): + if k == '.id': + continue + if k == 'dynamic' and include_dynamic: + continue + if k not in path_info.fields: + entry.pop(k) + if handle_disabled != 'omit': + for k in path_info.fields: + if k not in entry: + if handle_disabled == 'exclamation': + k = '!%s' % k + entry[k] = None + if hide_defaults: + for k, field_info in path_info.fields.items(): + if field_info.default is not None and entry.get(k) == field_info.default: + entry.pop(k) + result.append(entry) + + module.exit_json(result=result) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json(msg=to_native(e)) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py new file mode 100644 index 0000000..fe7a13e --- /dev/null +++ b/plugins/modules/api_modify.py @@ -0,0 +1,918 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: api_modify +author: + - "Felix Fontein (@felixfontein)" +short_description: Modify data at paths with API +version_added: 2.2.0 +description: + - Allows to modify information for a path using the API. + - Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way + depending on some search conditions. + - To make a backup of a path that can be restored with this module, use the M(community.routeros.api_info) module. + - The module ignores dynamic entries. + - B(Note) that this module is still heavily in development, and only supports B(some) paths. + If you want to support new paths, or think you found problems with existing paths, please first + L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). +notes: + - Supports I(check_mode). +requirements: + - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6 +extends_documentation_fragment: + - community.routeros.api +options: + path: + description: + - Path to query. + - An example value is C(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI. + required: true + type: str + choices: + # BEGIN PATH LIST + - caps-man aaa + - certificate settings + - interface bridge port + - interface bridge port-controller + - interface bridge port-extender + - interface bridge settings + - interface detect-internet + - interface ethernet + - interface ethernet switch + - interface ethernet switch port + - interface l2tp-server server + - interface ovpn-server server + - interface pptp-server server + - interface sstp-server server + - interface wireless align + - interface wireless cap + - interface wireless sniffer + - interface wireless snooper + - ip accounting + - ip accounting web-access + - ip address + - ip cloud + - ip cloud advanced + - ip dhcp-client + - ip dhcp-client option + - ip dhcp-server + - ip dhcp-server config + - ip dhcp-server lease + - ip dhcp-server network + - ip dns + - ip dns static + - ip firewall address-list + - ip firewall connection tracking + - ip firewall filter + - ip firewall nat + - ip firewall service-port + - ip hotspot service-port + - ip ipsec settings + - ip neighbor discovery-settings + - ip pool + - ip proxy + - ip service + - ip settings + - ip smb + - ip socks + - ip ssh + - ip tftp settings + - ip traffic-flow + - ip traffic-flow ipfix + - ip upnp + - ipv6 dhcp-client + - ipv6 firewall address-list + - ipv6 firewall filter + - ipv6 nd prefix default + - ipv6 settings + - mpls + - mpls ldp + - port firmware + - ppp aaa + - queue interface + - radius incoming + - routing bgp instance + - routing mme + - routing rip + - routing ripng + - snmp + - system clock + - system clock manual + - system identity + - system leds settings + - system note + - system ntp client + - system package update + - system routerboard settings + - system upgrade mirror + - system watchdog + - tool bandwidth-server + - tool e-mail + - tool graphing + - tool mac-server + - tool mac-server mac-winbox + - tool mac-server ping + - tool romon + - tool sms + - tool sniffer + - tool traffic-generator + - user aaa + - user group + # END PATH LIST + data: + description: + - Data to ensure that is present for this path. + - Fields not provided will not be modified. + - If C(.id) appears in an entry, it will be ignored. + required: true + type: list + elements: dict + ensure_order: + description: + - Whether to ensure the same order of the config as present in I(data). + - Requires I(handle_absent_entries=remove). + type: bool + default: false + handle_absent_entries: + description: + - How to handle entries that are present in the current config, but not in I(data). + - C(ignore) ignores them. + - C(remove) removes them. + type: str + choices: + - ignore + - remove + default: ignore + handle_entries_content: + description: + - For a single entry in I(data), this describes how to handle fields that are not mentioned + in that entry, but appear in the actual config. + - If C(ignore), they are not modified. + - If C(remove), they are removed. If at least one cannot be removed, the module will fail. + - If C(remove_as_much_as_possible), all that can be removed will be removed. The ones that + cannot be removed will be kept. + type: str + choices: + - ignore + - remove + - remove_as_much_as_possible + default: ignore +seealso: + - module: community.routeros.api + - module: community.routeros.api_facts + - module: community.routeros.api_find_and_modify + - module: community.routeros.api_info +''' + +EXAMPLES = ''' +--- +- name: Setup DHCP server networks + # Ensures that we have exactly two DHCP server networks (in the specified order) + community.routeros.api_modify: + path: ip dhcp-server network + handle_absent_entries: remove + handle_entries_content: remove_as_much_as_possible + ensure_order: true + data: + - address: 192.168.88.0/24 + comment: admin network + dns-server: 192.168.88.1 + gateway: 192.168.88.1 + - address: 192.168.1.0/24 + comment: customer network 1 + dns-server: 192.168.1.1 + gateway: 192.168.1.1 + netmask: 24 + +- name: Adjust NAT + community.routeros.api_modify: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: ip firewall nat + data: + - action: masquerade + chain: srcnat + comment: NAT to WAN + out-interface-list: WAN + # Three ways to unset values: + # - nothing after `:` + # - "empty" value (null/~/None) + # - prepend '!' + out-interface: + to-addresses: ~ + '!to-ports': +''' + +RETURN = ''' +--- +old_data: + description: + - A list of all elements for the current path before a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: always +new_data: + description: + - A list of all elements for the current path after a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.1.1/24" + comment: awesome + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.1.0 + type: list + elements: dict + returned: always +''' + +from collections import defaultdict + +from ansible.module_utils.basic import AnsibleModule, missing_required_lib +from ansible.module_utils.common.text.converters import to_native + +from ansible_collections.community.routeros.plugins.module_utils.api import ( + api_argument_spec, + check_has_library, + create_api, +) + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( + PATHS, + join_path, + split_path, +) + +HAS_ORDEREDDICT = True +try: + from collections import OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict + except ImportError: + HAS_ORDEREDDICT = False + OrderedDict = dict + +try: + from librouteros.exceptions import LibRouterosError +except Exception: + # Handled in api module_utils + pass + + +def compose_api_path(api, path): + api_path = api.path() + for p in path: + api_path = api_path.join(p) + return api_path + + +def find_modifications(old_entry, new_entry, path_info, module, for_text='', return_none_instead_of_fail=False): + modifications = OrderedDict() + updated_entry = old_entry.copy() + for k, v in new_entry.items(): + if k == '.id': + continue + disabled_k = None + if k.startswith('!'): + disabled_k = k[1:] + elif v is None or v == path_info.fields[k].remove_value: + disabled_k = k + if disabled_k is not None: + if disabled_k in old_entry: + if path_info.fields[disabled_k].remove_value is not None: + modifications[disabled_k] = path_info.fields[disabled_k].remove_value + else: + modifications['!%s' % disabled_k] = '' + del updated_entry[disabled_k] + continue + if k not in old_entry and path_info.fields[k].default == v: + continue + if k not in old_entry or old_entry[k] != v: + modifications[k] = v + updated_entry[k] = v + handle_entries_content = module.params['handle_entries_content'] + if handle_entries_content != 'ignore': + for k in old_entry: + if k == '.id' or k in new_entry or ('!%s' % k) in new_entry or k not in path_info.fields: + continue + field_info = path_info.fields[k] + if field_info.default is not None and field_info.default == old_entry[k]: + continue + if field_info.remove_value is not None and field_info.remove_value == old_entry[k]: + continue + if field_info.can_disable: + if field_info.remove_value is not None: + modifications[k] = field_info.remove_value + else: + modifications['!%s' % k] = '' + del updated_entry[k] + elif field_info.default is not None: + modifications[k] = field_info.default + updated_entry[k] = field_info.default + elif handle_entries_content == 'remove': + if return_none_instead_of_fail: + return None, None + module.fail_json(msg='Key "{key}" cannot be removed{for_text}.'.format(key=k, for_text=for_text)) + return modifications, updated_entry + + +def essentially_same_weight(old_entry, new_entry, path_info, module): + for k, v in new_entry.items(): + if k == '.id': + continue + disabled_k = None + if k.startswith('!'): + disabled_k = k[1:] + elif v is None or v == path_info.fields[k].remove_value: + disabled_k = k + if disabled_k is not None: + if disabled_k in old_entry: + return None + continue + if k not in old_entry and path_info.fields[k].default == v: + continue + if k not in old_entry or old_entry[k] != v: + return None + handle_entries_content = module.params['handle_entries_content'] + weight = 0 + for k in old_entry: + if k == '.id' or k in new_entry or ('!%s' % k) in new_entry or k not in path_info.fields: + continue + field_info = path_info.fields[k] + if field_info.default is not None and field_info.default == old_entry[k]: + continue + if handle_entries_content != 'ignore': + return None + else: + weight += 1 + return weight + + +def format_pk(primary_keys, values): + return ', '.join('{pk}="{value}"'.format(pk=pk, value=value) for pk, value in zip(primary_keys, values)) + + +def polish_entry(entry, path_info, module, for_text): + if '.id' in entry: + entry.pop('.id') + for key, value in entry.items(): + real_key = key + disabled_key = False + if key.startswith('!'): + disabled_key = True + key = key[1:] + if key in entry: + module.fail_json(msg='Not both "{key}" and "!{key}" must appear{for_text}.'.format(key=key, for_text=for_text)) + key_info = path_info.fields.get(key) + if key_info is None: + module.fail_json(msg='Unknown key "{key}"{for_text}.'.format(key=real_key, for_text=for_text)) + if disabled_key: + if not key_info.can_disable: + module.fail_json(msg='Key "!{key}" must not be disabled (leading "!"){for_text}.'.format(key=key, for_text=for_text)) + if value not in (None, '', key_info.remove_value): + module.fail_json(msg='Disabled key "!{key}" must not have a value{for_text}.'.format(key=key, for_text=for_text)) + elif value is None: + if not key_info.can_disable: + module.fail_json(msg='Key "{key}" must not be disabled (value null/~/None){for_text}.'.format(key=key, for_text=for_text)) + for key, field_info in path_info.fields.items(): + if field_info.required and key not in entry: + module.fail_json(msg='Key "{key}" must be present{for_text}.'.format(key=key, for_text=for_text)) + + +def remove_irrelevant_data(entry, path_info): + for k, v in list(entry.items()): + if k == '.id': + continue + if k not in path_info.fields or v is None: + del entry[k] + + +def match_entries(new_entries, old_entries, path_info, module): + matching_old_entries = [None for entry in new_entries] + old_entries = list(old_entries) + matches = [] + handle_absent_entries = module.params['handle_absent_entries'] + if handle_absent_entries == 'remove': + for new_index, (unused, new_entry) in enumerate(new_entries): + for old_index, (unused, old_entry) in enumerate(old_entries): + modifications, unused = find_modifications(old_entry, new_entry, path_info, module, return_none_instead_of_fail=True) + if modifications is not None: + matches.append((new_index, old_index, len(modifications))) + else: + for new_index, (unused, new_entry) in enumerate(new_entries): + for old_index, (unused, old_entry) in enumerate(old_entries): + weight = essentially_same_weight(old_entry, new_entry, path_info, module) + if weight is not None: + matches.append((new_index, old_index, weight)) + matches.sort(key=lambda entry: entry[2]) + for new_index, old_index, rating in matches: + if matching_old_entries[new_index] is not None or old_entries[old_index] is None: + continue + matching_old_entries[new_index], old_entries[old_index] = old_entries[old_index], None + unmatched_old_entries = [index_entry for index_entry in old_entries if index_entry is not None] + return matching_old_entries, unmatched_old_entries + + +def remove_dynamic(entries): + result = [] + for entry in entries: + if entry.get('dynamic', False): + continue + result.append(entry) + return result + + +def sync_list(module, api, path, path_info): + handle_absent_entries = module.params['handle_absent_entries'] + handle_entries_content = module.params['handle_entries_content'] + if handle_absent_entries == 'remove': + if handle_entries_content == 'ignore': + module.fail_json('For this path, handle_absent_entries=remove cannot be combined with handle_entries_content=ignore') + + stratify_keys = path_info.stratify_keys or () + + data = module.params['data'] + stratified_data = defaultdict(list) + for index, entry in enumerate(data): + for stratify_key in stratify_keys: + if stratify_key not in entry: + module.fail_json( + msg='Every element in data must contain "{stratify_key}". For example, the element at index #{index} does not provide it.'.format( + stratify_key=stratify_key, + index=index + 1, + ) + ) + sks = tuple(entry[stratify_key] for stratify_key in stratify_keys) + polish_entry( + entry, path_info, module, + ' at index {index}'.format(index=index + 1), + ) + stratified_data[sks].append((index, entry)) + stratified_data = dict(stratified_data) + + api_path = compose_api_path(api, path) + + old_data = list(api_path) + old_data = remove_dynamic(old_data) + stratified_old_data = defaultdict(list) + for index, entry in enumerate(old_data): + sks = tuple(entry[stratify_key] for stratify_key in stratify_keys) + stratified_old_data[sks].append((index, entry)) + stratified_old_data = dict(stratified_old_data) + + create_list = [] + modify_list = [] + remove_list = [] + + new_data = [] + for key, indexed_entries in stratified_data.items(): + old_entries = stratified_old_data.pop(key, []) + + # Try to match indexed_entries with old_entries + matching_old_entries, unmatched_old_entries = match_entries(indexed_entries, old_entries, path_info, module) + + # Update existing entries + for (index, new_entry), potential_old_entry in zip(indexed_entries, matching_old_entries): + if potential_old_entry is not None: + old_index, old_entry = potential_old_entry + modifications, updated_entry = find_modifications( + old_entry, new_entry, path_info, module, + ' at index {index}'.format(index=index + 1), + ) + # Add to modification list if there are changes + if modifications: + modifications['.id'] = old_entry['.id'] + modify_list.append(modifications) + new_data.append((old_index, updated_entry)) + new_entry['.id'] = old_entry['.id'] + else: + create_list.append(new_entry) + + if handle_absent_entries == 'remove': + remove_list.extend(entry['.id'] for index, entry in unmatched_old_entries) + else: + new_data.extend(unmatched_old_entries) + + for key, entries in stratified_old_data.items(): + if handle_absent_entries == 'remove': + remove_list.extend(entry['.id'] for index, entry in entries) + else: + new_data.extend(entries) + + new_data = [entry for index, entry in sorted(new_data, key=lambda entry: entry[0])] + new_data.extend(create_list) + + reorder_list = [] + if module.params['ensure_order']: + for index, entry in enumerate(data): + if '.id' in entry: + def match(current_entry): + return current_entry['.id'] == entry['.id'] + + else: + def match(current_entry): + return current_entry is entry + + current_index = next(current_index + index for current_index, current_entry in enumerate(new_data[index:]) if match(current_entry)) + if current_index != index: + reorder_list.append((index, new_data[current_index], new_data[index])) + new_data.insert(index, new_data.pop(current_index)) + + if not module.check_mode: + if remove_list: + try: + api_path.remove(*remove_list) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while removing {remove_list}: {error}'.format( + remove_list=', '.join(['ID {id}'.format(id=id) for id in remove_list]), + error=to_native(e), + ) + ) + for modifications in modify_list: + try: + api_path.update(**modifications) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while modifying for ID {id}: {error}'.format( + id=modifications['.id'], + error=to_native(e), + ) + ) + for entry in create_list: + try: + entry['.id'] = api_path.add(**entry) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while creating entry: {error}'.format( + error=to_native(e), + ) + ) + for new_index, new_entry, old_entry in reorder_list: + try: + for res in api_path('move', numbers=new_entry['.id'], destination=old_entry['.id']): + pass + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while moving entry ID {element_id} to position #{new_index} ID ({new_id}): {error}'.format( + element_id=new_entry['.id'], + new_index=new_index, + new_id=old_entry['.id'], + error=to_native(e), + ) + ) + + # For sake of completeness, retrieve the full new data: + if modify_list or create_list or reorder_list: + new_data = remove_dynamic(list(api_path)) + + # Remove 'irrelevant' data + for entry in old_data: + remove_irrelevant_data(entry, path_info) + for entry in new_data: + remove_irrelevant_data(entry, path_info) + + # Produce return value + more = {} + if module._diff: + more['diff'] = { + 'before': { + 'data': old_data, + }, + 'after': { + 'data': new_data, + }, + } + module.exit_json( + changed=bool(create_list or modify_list or remove_list or reorder_list), + old_data=old_data, + new_data=new_data, + **more + ) + + +def sync_with_primary_keys(module, api, path, path_info): + primary_keys = path_info.primary_keys + + if path_info.fixed_entries: + if module.params['ensure_order']: + module.fail_json(msg='ensure_order=true cannot be used with this path') + if module.params['handle_absent_entries'] == 'remove': + module.fail_json(msg='handle_absent_entries=remove cannot be used with this path') + + data = module.params['data'] + new_data_by_key = OrderedDict() + for index, entry in enumerate(data): + for primary_key in primary_keys: + if primary_key not in entry: + module.fail_json( + msg='Every element in data must contain "{primary_key}". For example, the element at index #{index} does not provide it.'.format( + primary_key=primary_key, + index=index + 1, + ) + ) + pks = tuple(entry[primary_key] for primary_key in primary_keys) + if pks in new_data_by_key: + module.fail_json( + msg='Every element in data must contain a unique value for {primary_keys}. The value {value} appears at least twice.'.format( + primary_keys=','.join(primary_keys), + value=','.join(['"{0}"'.format(pk) for pk in pks]), + ) + ) + polish_entry( + entry, path_info, module, + ' for {values}'.format( + values=', '.join([ + '{primary_key}="{value}"'.format(primary_key=primary_key, value=value) + for primary_key, value in zip(primary_keys, pks) + ]) + ), + ) + new_data_by_key[pks] = entry + + api_path = compose_api_path(api, path) + + old_data = list(api_path) + old_data = remove_dynamic(old_data) + old_data_by_key = OrderedDict() + id_by_key = {} + for entry in old_data: + pks = tuple(entry[primary_key] for primary_key in primary_keys) + old_data_by_key[pks] = entry + id_by_key[pks] = entry['.id'] + new_data = [] + + create_list = [] + modify_list = [] + remove_list = [] + remove_keys = [] + handle_absent_entries = module.params['handle_absent_entries'] + for key, old_entry in old_data_by_key.items(): + new_entry = new_data_by_key.pop(key, None) + if new_entry is None: + if handle_absent_entries == 'remove': + remove_list.append(old_entry['.id']) + remove_keys.append(key) + else: + new_data.append(old_entry) + else: + modifications, updated_entry = find_modifications( + old_entry, new_entry, path_info, module, + ' for {values}'.format( + values=', '.join([ + '{primary_key}="{value}"'.format(primary_key=primary_key, value=value) + for primary_key, value in zip(primary_keys, key) + ]) + ) + ) + new_data.append(updated_entry) + # Add to modification list if there are changes + if modifications: + modifications['.id'] = old_entry['.id'] + modify_list.append((key, modifications)) + for new_entry in new_data_by_key.values(): + if path_info.fixed_entries: + module.fail_json(msg='Cannot add new entry {values} to this path'.format( + values=', '.join([ + '{primary_key}="{value}"'.format(primary_key=primary_key, value=new_entry[primary_key]) + for primary_key in primary_keys + ]), + )) + create_list.append(new_entry) + new_entry = new_entry.copy() + for key in list(new_entry): + if key.startswith('!'): + new_entry.pop(key) + new_data.append(new_entry) + + reorder_list = [] + if module.params['ensure_order']: + index_by_key = dict() + for index, entry in enumerate(new_data): + index_by_key[tuple(entry[primary_key] for primary_key in primary_keys)] = index + for index, source_entry in enumerate(data): + source_pks = tuple(source_entry[primary_key] for primary_key in primary_keys) + source_index = index_by_key.pop(source_pks) + if index == source_index: + continue + entry = new_data[index] + pks = tuple(entry[primary_key] for primary_key in primary_keys) + reorder_list.append((source_pks, index, pks)) + for k, v in index_by_key.items(): + if v >= index and v < source_index: + index_by_key[k] = v + 1 + new_data.insert(index, new_data.pop(source_index)) + + if not module.check_mode: + if remove_list: + try: + api_path.remove(*remove_list) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while removing {remove_list}: {error}'.format( + remove_list=', '.join([ + '{identifier} (ID {id})'.format(identifier=format_pk(primary_keys, key), id=id) + for id, key in zip(remove_list, remove_keys) + ]), + error=to_native(e), + ) + ) + for key, modifications in modify_list: + try: + api_path.update(**modifications) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while modifying for {identifier} (ID {id}): {error}'.format( + identifier=format_pk(primary_keys, key), + id=modifications['.id'], + error=to_native(e), + ) + ) + for entry in create_list: + try: + entry['.id'] = api_path.add(**entry) + # Store ID for primary keys + pks = tuple(entry[primary_key] for primary_key in primary_keys) + id_by_key[pks] = entry['.id'] + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while creating entry for {identifier}: {error}'.format( + identifier=format_pk(primary_keys, [entry[pk] for pk in primary_keys]), + error=to_native(e), + ) + ) + for element_pks, new_index, new_pks in reorder_list: + try: + element_id = id_by_key[element_pks] + new_id = id_by_key[new_pks] + for res in api_path('move', numbers=element_id, destination=new_id): + pass + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json( + msg='Error while moving entry ID {element_id} to position of ID {new_id}: {error}'.format( + element_id=element_id, + new_id=new_id, + error=to_native(e), + ) + ) + + # For sake of completeness, retrieve the full new data: + if modify_list or create_list or reorder_list: + new_data = remove_dynamic(list(api_path)) + + # Remove 'irrelevant' data + for entry in old_data: + remove_irrelevant_data(entry, path_info) + for entry in new_data: + remove_irrelevant_data(entry, path_info) + + # Produce return value + more = {} + if module._diff: + more['diff'] = { + 'before': { + 'data': old_data, + }, + 'after': { + 'data': new_data, + }, + } + module.exit_json( + changed=bool(create_list or modify_list or remove_list or reorder_list), + old_data=old_data, + new_data=new_data, + **more + ) + + +def sync_single_value(module, api, path, path_info): + data = module.params['data'] + if len(data) != 1: + module.fail_json(msg='Data must be a list with exactly one element.') + new_entry = data[0] + polish_entry(new_entry, path_info, module, '') + + api_path = compose_api_path(api, path) + + old_data = list(api_path) + if len(old_data) != 1: + module.fail_json( + msg='Internal error: retrieving /{path} resulted in {count} elements. Expected exactly 1.'.format( + path=join_path(path), + count=len(old_data) + ) + ) + old_entry = old_data[0] + + # Determine modifications + modifications, updated_entry = find_modifications(old_entry, new_entry, path_info, module, '') + # Do modifications + if modifications: + if not module.check_mode: + # Actually do modification + try: + api_path.update(**modifications) + except (LibRouterosError, UnicodeEncodeError) as e: + module.fail_json(msg='Error while modifying: {error}'.format(error=to_native(e))) + # Retrieve latest version + new_data = list(api_path) + if len(new_data) == 1: + updated_entry = new_data[0] + + # Remove 'irrelevant' data + remove_irrelevant_data(old_entry, path_info) + remove_irrelevant_data(updated_entry, path_info) + + # Produce return value + more = {} + if module._diff: + more['diff'] = { + 'before': old_entry, + 'after': updated_entry, + } + module.exit_json( + changed=bool(modifications), + old_data=[old_entry], + new_data=[updated_entry], + **more + ) + + +def get_backend(path_info): + if path_info is None: + return None + if not path_info.fully_understood: + return None + + if path_info.primary_keys: + return sync_with_primary_keys + + if path_info.single_value: + return sync_single_value + + if not path_info.has_identifier: + return sync_list + + return None + + +def main(): + path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if get_backend(path_info) is not None]) + module_args = dict( + path=dict(type='str', required=True, choices=path_choices), + data=dict(type='list', elements='dict', required=True), + handle_absent_entries=dict(type='str', choices=['ignore', 'remove'], default='ignore'), + handle_entries_content=dict(type='str', choices=['ignore', 'remove', 'remove_as_much_as_possible'], default='ignore'), + ensure_order=dict(type='bool', default=False), + ) + module_args.update(api_argument_spec()) + + module = AnsibleModule( + argument_spec=module_args, + supports_check_mode=True, + ) + if module.params['ensure_order'] and module.params['handle_absent_entries'] == 'ignore': + module.fail_json(msg='ensure_order=true requires handle_absent_entries=remove') + + if not HAS_ORDEREDDICT: + # This should never happen for Python 2.7+ + module.fail_json(msg=missing_required_lib('ordereddict')) + + check_has_library(module) + api = create_api(module) + + path = split_path(module.params['path']) + path_info = PATHS.get(tuple(path)) + backend = get_backend(path_info) + if path_info is None or backend is None: + module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) + + backend(module, api, path, path_info) + + +if __name__ == '__main__': + main() diff --git a/tests/sanity/extra/update-docs.json b/tests/sanity/extra/update-docs.json new file mode 100644 index 0000000..f6f87b7 --- /dev/null +++ b/tests/sanity/extra/update-docs.json @@ -0,0 +1,8 @@ +{ + "include_symlinks": false, + "prefixes": [ + "docs/docsite/rst/api-guide.rst", + "plugins/modules/", + ], + "output": "path-line-column-message", +} diff --git a/tests/sanity/extra/update-docs.py b/tests/sanity/extra/update-docs.py new file mode 100644 index 0000000..139fd87 --- /dev/null +++ b/tests/sanity/extra/update-docs.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +"""Check whether update-docs.py modifies something.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import sys +import subprocess + + +def main(): + """Main entry point.""" + p = subprocess.run(['./update-docs.py'], check=False) + if p.returncode not in (0, 1): + print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) + + +if __name__ == '__main__': + main() diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt new file mode 100644 index 0000000..876765a --- /dev/null +++ b/tests/sanity/ignore-2.10.txt @@ -0,0 +1,6 @@ +update-docs.py compile-2.6 +update-docs.py compile-2.7 +update-docs.py compile-3.5 +update-docs.py future-import-boilerplate +update-docs.py metaclass-boilerplate +update-docs.py shebang diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt new file mode 100644 index 0000000..876765a --- /dev/null +++ b/tests/sanity/ignore-2.11.txt @@ -0,0 +1,6 @@ +update-docs.py compile-2.6 +update-docs.py compile-2.7 +update-docs.py compile-3.5 +update-docs.py future-import-boilerplate +update-docs.py metaclass-boilerplate +update-docs.py shebang diff --git a/tests/sanity/ignore-2.12.txt b/tests/sanity/ignore-2.12.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.12.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.13.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.14.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt new file mode 100644 index 0000000..876765a --- /dev/null +++ b/tests/sanity/ignore-2.9.txt @@ -0,0 +1,6 @@ +update-docs.py compile-2.6 +update-docs.py compile-2.7 +update-docs.py compile-3.5 +update-docs.py future-import-boilerplate +update-docs.py metaclass-boilerplate +update-docs.py shebang diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index 95d59ba..0a3f608 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -130,8 +130,10 @@ def _normalize_entry(entry, path_info): del entry['!%s' % key] -def massage_expected_result_data(values, path, keep_all=False): +def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=False): path_info = PATHS[path] + if remove_dynamic: + values = [entry for entry in values if not entry.get('dynamic', False)] values = [entry.copy() for entry in values] for entry in values: _normalize_entry(entry, path_info) diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py new file mode 100644 index 0000000..2195d20 --- /dev/null +++ b/tests/unit/plugins/modules/test_api_info.py @@ -0,0 +1,408 @@ +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json +import pytest + +from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api +from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase +from ansible_collections.community.routeros.plugins.modules import api_info + + +class TestRouterosApiInfoModule(ModuleTestCase): + + def setUp(self): + super(TestRouterosApiInfoModule, self).setUp() + self.module = api_info + self.module.LibRouterosError = FakeLibRouterosError + self.module.connect = MagicMock(new=fake_ros_api) + self.module.check_has_library = MagicMock() + self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api_info.create_api', MagicMock(new=fake_ros_api)) + self.patch_create_api.start() + self.module.Key = MagicMock(new=Key) + self.config_module_args = { + 'username': 'admin', + 'password': 'pаss', + 'hostname': '127.0.0.1', + } + + def tearDown(self): + self.patch_create_api.stop() + + def test_module_fail_when_required_args_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + set_module_args({}) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + + def test_invalid_path(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'something invalid' + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'].startswith('value of path must be one of: '), True) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_empty_result(self, mock_compose_api_path): + mock_compose_api_path.return_value = [] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static' + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], []) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_regular_result(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'called-format': 'mac:ssid', + 'interim-update': 'enabled', + 'mac-caching': 'disabled', + 'mac-format': 'XX:XX:XX:XX:XX:XX', + 'mac-mode': 'as-username', + 'foo': 'bar', + '.id': '*1', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'caps-man aaa', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'interim-update': 'enabled', + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_result_with_defaults(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'called-format': 'mac:ssid', + 'interim-update': 'enabled', + 'mac-caching': 'disabled', + 'mac-format': 'XX:XX:XX:XX:XX:XX', + 'mac-mode': 'as-username', + 'foo': 'bar', + '.id': '*1', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'caps-man aaa', + 'hide_defaults': False, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'called-format': 'mac:ssid', + 'interim-update': 'enabled', + 'mac-caching': 'disabled', + 'mac-format': 'XX:XX:XX:XX:XX:XX', + 'mac-mode': 'as-username', + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_full_result(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'called-format': 'mac:ssid', + 'interim-update': 'enabled', + 'mac-caching': 'disabled', + 'mac-format': 'XX:XX:XX:XX:XX:XX', + 'mac-mode': 'as-username', + 'foo': 'bar', + '.id': '*1', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'caps-man aaa', + 'unfiltered': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'interim-update': 'enabled', + 'foo': 'bar', + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_disabled_exclamation(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + 'dynamic': False, + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': True, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'exclamation', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'chain': 'input', + 'in-interface-list': 'LAN', + '!action': None, + '!comment': None, + '!connection-bytes': None, + '!connection-limit': None, + '!connection-mark': None, + '!connection-nat-state': None, + '!connection-rate': None, + '!connection-state': None, + '!connection-type': None, + '!content': None, + '!disabled': None, + '!dscp': None, + '!dst-address': None, + '!dst-address-list': None, + '!dst-address-type': None, + '!dst-limit': None, + '!dst-port': None, + '!fragment': None, + '!hotspot': None, + '!icmp-options': None, + '!in-bridge-port': None, + '!in-bridge-port-list': None, + '!in-interface': None, + '!ingress-priority': None, + '!ipsec-policy': None, + '!ipv4-options': None, + '!layer7-protocol': None, + '!limit': None, + '!log': None, + '!log-prefix': None, + '!nth': None, + '!out-bridge-port': None, + '!out-bridge-port-list': None, + '!out-interface': None, + '!out-interface-list': None, + '!p2p': None, + '!packet-mark': None, + '!packet-size': None, + '!per-connection-classifier': None, + '!port': None, + '!priority': None, + '!protocol': None, + '!psd': None, + '!random': None, + '!routing-mark': None, + '!routing-table': None, + '!src-address': None, + '!src-address-list': None, + '!src-address-type': None, + '!src-mac-address': None, + '!src-port': None, + '!tcp-flags': None, + '!tcp-mss': None, + '!time': None, + '!tls-host': None, + '!ttl': None, + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_disabled_null_value(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + 'dynamic': False, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'null-value', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'chain': 'input', + 'in-interface-list': 'LAN', + 'action': None, + 'comment': None, + 'connection-bytes': None, + 'connection-limit': None, + 'connection-mark': None, + 'connection-nat-state': None, + 'connection-rate': None, + 'connection-state': None, + 'connection-type': None, + 'content': None, + 'disabled': None, + 'dscp': None, + 'dst-address': None, + 'dst-address-list': None, + 'dst-address-type': None, + 'dst-limit': None, + 'dst-port': None, + 'fragment': None, + 'hotspot': None, + 'icmp-options': None, + 'in-bridge-port': None, + 'in-bridge-port-list': None, + 'in-interface': None, + 'ingress-priority': None, + 'ipsec-policy': None, + 'ipv4-options': None, + 'layer7-protocol': None, + 'limit': None, + 'log': None, + 'log-prefix': None, + 'nth': None, + 'out-bridge-port': None, + 'out-bridge-port-list': None, + 'out-interface': None, + 'out-interface-list': None, + 'p2p': None, + 'packet-mark': None, + 'packet-size': None, + 'per-connection-classifier': None, + 'port': None, + 'priority': None, + 'protocol': None, + 'psd': None, + 'random': None, + 'routing-mark': None, + 'routing-table': None, + 'src-address': None, + 'src-address-list': None, + 'src-address-type': None, + 'src-mac-address': None, + 'src-port': None, + 'tcp-flags': None, + 'tcp-mss': None, + 'time': None, + 'tls-host': None, + 'ttl': None, + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_disabled_omit(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + 'dynamic': False, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'omit', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [{ + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + }]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_dynamic(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + 'dynamic': False, + '.id': '*1', + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': True, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'omit', + 'include_dynamic': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + 'dynamic': False, + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': True, + }, + ]) diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py new file mode 100644 index 0000000..5c5d4ee --- /dev/null +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -0,0 +1,1540 @@ +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json +import pytest + +from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( + FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, +) +from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase +from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS +from ansible_collections.community.routeros.plugins.modules import api_modify + + +START_IP_DNS_STATIC = [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'dynamic': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'dynamic': False, + }, + { + '.id': '*7', + 'comment': '', + 'name': 'foo', + 'address': '192.168.88.2', + 'dynamic': False, + }, + { + '.id': '*8', + 'comment': '', + 'name': 'dynfoo', + 'address': '192.168.88.15', + 'dynamic': True, + }, +] + +START_IP_DNS_STATIC_OLD_DATA = massage_expected_result_data(START_IP_DNS_STATIC, ('ip', 'dns', 'static'), remove_dynamic=True) + +START_IP_SETTINGS = [ + { + 'accept-redirects': True, + 'accept-source-route': False, + 'allow-fast-path': True, + 'arp-timeout': '30s', + 'icmp-rate-limit': 20, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 8192, + 'route-cache': True, + 'rp-filter': False, + 'secure-redirects': True, + 'send-redirects': True, + 'tcp-syncookies': False, + }, +] + +START_IP_SETTINGS_OLD_DATA = massage_expected_result_data(START_IP_SETTINGS, ('ip', 'settings')) + +START_IP_ADDRESS = [ + { + '.id': '*1', + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'disabled': False, + }, + { + '.id': '*3', + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': False, + }, + { + '.id': '*F', + 'address': '10.0.0.0/16', + 'interface': 'WAN', + 'disabled': True, + }, +] + +START_IP_ADDRESS_OLD_DATA = massage_expected_result_data(START_IP_ADDRESS, ('ip', 'address')) + + +class TestRouterosApiModifyModule(ModuleTestCase): + + def setUp(self): + super(TestRouterosApiModifyModule, self).setUp() + self.module = api_modify + self.module.LibRouterosError = FakeLibRouterosError + self.module.connect = MagicMock(new=fake_ros_api) + self.module.check_has_library = MagicMock() + self.patch_create_api = patch( + 'ansible_collections.community.routeros.plugins.modules.api_modify.create_api', + MagicMock(new=fake_ros_api)) + self.patch_create_api.start() + self.config_module_args = { + 'username': 'admin', + 'password': 'pаss', + 'hostname': '127.0.0.1', + } + + def tearDown(self): + self.patch_create_api.stop() + + def test_module_fail_when_required_args_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + set_module_args({}) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + + def test_invalid_path(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'something invalid', + 'data': [], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'].startswith('value of path must be one of: '), True) + + def test_invalid_option(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': 'baz', + 'foo': 'bar', + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Unknown key "foo" at index 1.') + + def test_invalid_disabled_and_enabled_option(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': 'baz', + 'comment': 'foo', + '!comment': None, + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Not both "comment" and "!comment" must appear at index 1.') + + def test_invalid_disabled_option(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': 'foo', + '!disabled': None, + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Key "!disabled" must not be disabled (leading "!") at index 1.') + + def test_invalid_disabled_option_value(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': 'baz', + '!comment': 'foo', + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Disabled key "!comment" must not have a value at index 1.') + + def test_invalid_non_disabled_option_value(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': None, + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Key "name" must not be disabled (value null/~/None) at index 1.') + + def test_invalid_required_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'address': '1.2.3.4', + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Every element in data must contain "name". For example, the element at index #1 does not provide it.') + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_idempotent(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + '.id': 'bam', # this should be ignored + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + { + 'comment': None, + 'name': 'router', + 'text': 'Router Text Entry', + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_idempotent_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'foo', + 'comment': '', + 'address': '192.168.88.2', + }, + { + 'name': 'router', + '!comment': None, + 'text': 'Router Text Entry', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_idempotent_3(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DNS_STATIC_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_add(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'text': 'Router Text Entry', + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*NEW1', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_modify_1(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*NEW1', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_modify_1_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_modify_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': '', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_modify_2_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': '', + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_modify_3(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + '!comment': None, + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'cname': 'router.com.', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*NEW1', + 'name': 'router', + 'cname': 'router.com.', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_modify_3_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + '!comment': None, + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'cname': 'router.com.', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + 'name': 'router', + 'cname': 'router.com.', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_modify_4(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'comment': 'defconf', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'comment': 'defconf', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_modify_4_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'name': 'router', + 'address': '192.168.88.1', + }, + { + 'name': 'router', + 'comment': 'defconf', + 'text': 'Router Text Entry 2', + }, + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'comment': 'defconf', + 'name': 'router', + 'text': 'Router Text Entry 2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_delete(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_delete_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC)) + def test_sync_list_reorder(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + { + 'name': 'foo', + 'text': 'bar', + }, + { + 'name': 'router', + 'text': 'Router Text Entry', + }, + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*NEW1', + 'name': 'foo', + 'text': 'bar', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) + def test_sync_list_reorder_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [ + { + 'name': 'foo', + 'address': '192.168.88.2', + }, + { + 'name': 'foo', + 'text': 'bar', + }, + { + 'name': 'router', + 'text': 'Router Text Entry', + }, + { + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_DNS_STATIC_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*7', + 'name': 'foo', + 'address': '192.168.88.2', + 'ttl': '1d', + 'disabled': False, + }, + { + 'name': 'foo', + 'text': 'bar', + }, + { + '.id': '*A', + 'name': 'router', + 'text': 'Router Text Entry', + 'ttl': '1d', + 'disabled': False, + }, + { + '.id': '*1', + 'comment': 'defconf', + 'name': 'router', + 'address': '192.168.88.1', + 'ttl': '1d', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS, read_only=True)) + def test_sync_value_idempotent(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'arp-timeout': '30s', + 'icmp-rate-limit': 20, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 8192, + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_SETTINGS_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS, read_only=True)) + def test_sync_value_idempotent_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'accept-redirects': True, + 'icmp-rate-limit': 20, + }, + ], + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_SETTINGS_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS)) + def test_sync_value_modify(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'max-neighbor-entries': 4096, + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'allow-fast-path': True, + 'arp-timeout': '30s', + 'icmp-rate-limit': 20, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 4096, + 'route-cache': True, + 'rp-filter': False, + 'secure-redirects': True, + 'send-redirects': True, + 'tcp-syncookies': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS, read_only=True)) + def test_sync_value_modify_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'max-neighbor-entries': 4096, + }, + ], + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'allow-fast-path': True, + 'arp-timeout': '30s', + 'icmp-rate-limit': 20, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 4096, + 'route-cache': True, + 'rp-filter': False, + 'secure-redirects': True, + 'send-redirects': True, + 'tcp-syncookies': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS)) + def test_sync_value_modify_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'max-neighbor-entries': 4096, + }, + ], + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'allow-fast-path': True, + 'arp-timeout': '30s', + 'icmp-rate-limit': 10, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 4096, + 'route-cache': True, + 'rp-filter': False, + 'secure-redirects': True, + 'send-redirects': True, + 'tcp-syncookies': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'settings'), START_IP_SETTINGS, read_only=True)) + def test_sync_value_modify_2_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip settings', + 'data': [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'max-neighbor-entries': 4096, + }, + ], + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_SETTINGS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + 'accept-redirects': True, + 'accept-source-route': True, + 'allow-fast-path': True, + 'arp-timeout': '30s', + 'icmp-rate-limit': 10, + 'icmp-rate-mask': '0x1818', + 'ip-forward': True, + 'max-neighbor-entries': 4096, + 'route-cache': True, + 'rp-filter': False, + 'secure-redirects': True, + 'send-redirects': True, + 'tcp-syncookies': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS, read_only=True)) + def test_sync_primary_key_idempotent(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'comment': '', + }, + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + '!comment': None, + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_ADDRESS_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS, read_only=True)) + def test_sync_primary_key_idempotent_2(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + }, + { + 'address': '10.0.0.0/16', + 'interface': 'WAN', + 'disabled': True, + '!comment': '', + }, + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': False, + 'comment': None, + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_ADDRESS_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS)) + def test_sync_primary_key_cru(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'comment': 'foo', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'foo', + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'disabled': False, + }, + { + '.id': '*3', + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + '.id': '*NEW1', + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS, read_only=True)) + def test_sync_primary_key_cru_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'comment': 'foo', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*1', + 'comment': 'foo', + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'disabled': False, + }, + { + '.id': '*3', + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS)) + def test_sync_primary_key_cru_reorder(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'comment': 'foo', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + '.id': '*NEW1', + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + 'disabled': False, + }, + { + '.id': '*3', + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + '.id': '*1', + 'comment': 'foo', + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'disabled': False, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'address'), START_IP_ADDRESS, read_only=True)) + def test_sync_primary_key_cru_reorder_check(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip address', + 'data': [ + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + { + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'comment': 'foo', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + '_ansible_check_mode': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], START_IP_ADDRESS_OLD_DATA) + self.assertEqual(result['new_data'], [ + { + 'address': '10.10.0.0/16', + 'interface': 'WIFI', + }, + { + '.id': '*3', + 'address': '192.168.1.0/24', + 'interface': 'LAN', + 'disabled': True, + }, + { + '.id': '*1', + 'comment': 'foo', + 'address': '192.168.88.0/24', + 'interface': 'bridge', + 'disabled': False, + }, + ]) diff --git a/update-docs.py b/update-docs.py new file mode 100755 index 0000000..6f4fef8 --- /dev/null +++ b/update-docs.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +''' +Updates DOCUMENTATION of modules using module_utils._api_data with the correct list of supported paths. +''' + +import os + +from plugins.module_utils._api_data import ( + PATHS, + join_path, +) + + +MODULES = [ + 'plugins/modules/api_info.py', + 'plugins/modules/api_modify.py', +] + + +def update_file(file, begin_line, end_line, choice_line, path_choices): + with open(file, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + begin_index = lines.index(begin_line) + end_index = lines.index(end_line, begin_index + 1) + new_lines = lines[:begin_index + 1] + [choice_line.format(choice=choice) for choice in path_choices] + lines[end_index:] + if lines != new_lines: + print(f'{file} has been updated') + with open(file, 'w', encoding='utf-8') as f: + f.write('\n'.join(new_lines) + '\n') + + +def main(): + path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if path_info.fully_understood]) + + for file in MODULES: + update_file(file, ' # BEGIN PATH LIST', ' # END PATH LIST', ' - {choice}', path_choices) + + +if __name__ == '__main__': + main() From fa13c5f9cb920cbaccc26938a4981bcdfafac79d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 31 Jul 2022 22:08:09 +0200 Subject: [PATCH 047/365] Prepare 2.2.0 release. --- changelogs/fragments/2.2.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.2.0.yml diff --git a/changelogs/fragments/2.2.0.yml b/changelogs/fragments/2.2.0.yml new file mode 100644 index 0000000..1a32859 --- /dev/null +++ b/changelogs/fragments/2.2.0.yml @@ -0,0 +1 @@ +release_summary: New feature release. diff --git a/galaxy.yml b/galaxy.yml index 2ba0a85..443cee9 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.1.0 +version: 2.2.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From a66bb78d7fa8cda4fb2661e01825eb778717b970 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 31 Jul 2022 22:30:07 +0200 Subject: [PATCH 048/365] Release 2.2.0. --- CHANGELOG.rst | 24 ++++++++++++++++++++++++ changelogs/changelog.yaml | 21 +++++++++++++++++++++ changelogs/fragments/101-licenses.yml | 4 ---- changelogs/fragments/2.2.0.yml | 1 - 4 files changed, 45 insertions(+), 5 deletions(-) delete mode 100644 changelogs/fragments/101-licenses.yml delete mode 100644 changelogs/fragments/2.2.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8bad8be..6042ae9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,30 @@ Community RouterOS Release Notes .. contents:: Topics +v2.2.0 +====== + +Release Summary +--------------- + +New feature release. + +Minor Changes +------------- + +- All software licenses are now in the ``LICENSES/`` directory of the collection root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101). + +Bugfixes +-------- + +- Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils (https://github.com/ansible-collections/community.routeros/pull/101). + +New Modules +----------- + +- api_info - Retrieve information from API +- api_modify - Modify data at paths with API + v2.1.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 8872b1d..2645fa6 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -189,3 +189,24 @@ releases: name: api_find_and_modify namespace: '' release_date: '2022-05-25' + 2.2.0: + changes: + bugfixes: + - Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils + (https://github.com/ansible-collections/community.routeros/pull/101). + minor_changes: + - All software licenses are now in the ``LICENSES/`` directory of the collection + root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable + license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101). + release_summary: New feature release. + fragments: + - 101-licenses.yml + - 2.2.0.yml + modules: + - description: Retrieve information from API + name: api_info + namespace: '' + - description: Modify data at paths with API + name: api_modify + namespace: '' + release_date: '2022-07-31' diff --git a/changelogs/fragments/101-licenses.yml b/changelogs/fragments/101-licenses.yml deleted file mode 100644 index e54f8a2..0000000 --- a/changelogs/fragments/101-licenses.yml +++ /dev/null @@ -1,4 +0,0 @@ -minor_changes: - - "All software licenses are now in the ``LICENSES/`` directory of the collection root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101)." -bugfixes: - - "Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils (https://github.com/ansible-collections/community.routeros/pull/101)." diff --git a/changelogs/fragments/2.2.0.yml b/changelogs/fragments/2.2.0.yml deleted file mode 100644 index 1a32859..0000000 --- a/changelogs/fragments/2.2.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: New feature release. From af6524a1fd4cf6e56448be464124e2bf76ba1e53 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 4 Aug 2022 14:32:01 +0200 Subject: [PATCH 049/365] Fix docs. (#105) --- plugins/modules/api.py | 4 +++- plugins/modules/api_facts.py | 3 ++- plugins/modules/facts.py | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 3ba80d2..ea667a5 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -246,7 +246,9 @@ RETURN = ''' --- message: description: All outputs are in list with dictionary elements returned from RouterOS api. - sample: C([{...},{...}]) + sample: + - address: 1.2.3.4 + - address: 2.3.4.5 type: list returned: always ''' diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 7209f2a..7db910c 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -38,7 +38,8 @@ options: Values can also be used with an initial C(!) to specify that a specific subset should not be collected. required: false - default: 'all' + default: + - all type: list elements: str seealso: diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 383f940..cefaf5c 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -28,7 +28,8 @@ options: Values can also be used with an initial C(!) to specify that a specific subset should not be collected. required: false - default: '!config' + default: + - '!config' type: list elements: str seealso: From 98bb520ce78942f5bca0a19ad782d1be40e29cb0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 4 Aug 2022 22:34:00 +0200 Subject: [PATCH 050/365] Use ansible-community/ansible-test-gh-action for CI (#103) * Use ansible-community/ansible-test-gh-action for CI Based upon https://github.com/ansible-collections/collection_template/pull/29. * Avoid trailing ';'. * Fix relative paths for collection installs. * Try multi-line command. * Prevent trailing newline. --- .github/workflows/ansible-test.yml | 153 +++++++---------------------- 1 file changed, 33 insertions(+), 120 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 1343492..23395cf 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -3,6 +3,9 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later +# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see +# https://github.com/marketplace/actions/ansible-test + name: CI on: # Run CI against all pushes (direct commits, also merged PRs), Pull Requests @@ -16,12 +19,6 @@ on: - cron: '15 5 * * *' jobs: - -### -# Sanity tests (REQUIRED) -# -# https://docs.ansible.com/ansible/latest/dev_guide/testing_sanity.html - sanity: name: Sanity (Ⓐ${{ matrix.ansible }}) strategy: @@ -37,52 +34,15 @@ jobs: - devel runs-on: ubuntu-latest steps: - - # ansible-test requires the collection to be in a directory in the form - # .../ansible_collections/community/routeros/ - - - name: Check out code - uses: actions/checkout@v3 + - name: Perform sanity testing + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ansible_collections/community/routeros - - - name: Set up Python - uses: actions/setup-python@v3 - with: - # it is just required to run that once as "ansible-test sanity" in the docker image - # will run on all python versions it supports. - python-version: '3.10' - - # Install the head of the given branch (devel, stable-2.10) - - 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: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # 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 --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@v3 - with: - fail_ci_if_error: false - -### -# Unit tests (OPTIONAL) -# -# https://docs.ansible.com/ansible/latest/dev_guide/testing_units.html + ansible-core-version: ${{ matrix.ansible }} + testing-type: sanity + # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) + pre-test-cmd: |- + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils units: runs-on: ubuntu-latest @@ -100,43 +60,17 @@ jobs: - devel steps: - - name: Check out code - uses: actions/checkout@v3 + - name: >- + Perform unit testing against + Ansible version ${{ matrix.ansible }} + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ansible_collections/community/routeros - - - name: Set up Python ${{ matrix.ansible }} - uses: actions/setup-python@v3 - with: - python-version: '3.10' - - - 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: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # run: ansible-galaxy collection install ansible.netcommon -p . - - # Run the unit tests - - name: Run unit tests for all Python versions - run: ansible-test units -v --color --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@v3 - with: - fail_ci_if_error: false - -### -# Integration tests (RECOMMENDED) -# -# https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html + ansible-core-version: ${{ matrix.ansible }} + testing-type: units + # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) + pre-test-cmd: |- + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils integration: runs-on: ubuntu-latest @@ -176,37 +110,16 @@ jobs: python: "3.10" steps: - - name: Check out code - uses: actions/checkout@v3 + - name: >- + Perform integration testing against + Ansible version ${{ matrix.ansible }} + under Python ${{ matrix.python }} + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ansible_collections/community/routeros - - - name: Set up Python - uses: actions/setup-python@v3 - with: - # it is just required to run that once as "ansible-test integration" in the docker image - # will run on all python versions it supports. - python-version: '3.10' - - - name: Install ansible-core (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - - name: Install collection dependencies - run: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # 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/community.routeros - - uses: codecov/codecov-action@v3 - with: - fail_ci_if_error: false + ansible-core-version: ${{ matrix.ansible }} + # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) + pre-test-cmd: |- + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + target-python-version: ${{ matrix.python }} + testing-type: integration From ec98df2f49cf4fd073249f97b6b5dff94f86b688 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 10 Aug 2022 20:44:32 +0200 Subject: [PATCH 051/365] Fix CI. --- .github/workflows/ansible-test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 23395cf..b4183f1 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -43,6 +43,7 @@ jobs: pre-test-cmd: |- git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + collection-root: '' units: runs-on: ubuntu-latest @@ -71,6 +72,7 @@ jobs: pre-test-cmd: |- git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + collection-root: '' integration: runs-on: ubuntu-latest @@ -123,3 +125,4 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils target-python-version: ${{ matrix.python }} testing-type: integration + collection-root: '' From 96c6feff8eca7e5576f146541186cfaf97436ab2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 11 Aug 2022 22:43:19 +0200 Subject: [PATCH 052/365] Revert "Fix CI." This reverts commit ec98df2f49cf4fd073249f97b6b5dff94f86b688. --- .github/workflows/ansible-test.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index b4183f1..23395cf 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -43,7 +43,6 @@ jobs: pre-test-cmd: |- git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils - collection-root: '' units: runs-on: ubuntu-latest @@ -72,7 +71,6 @@ jobs: pre-test-cmd: |- git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils - collection-root: '' integration: runs-on: ubuntu-latest @@ -125,4 +123,3 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils target-python-version: ${{ matrix.python }} testing-type: integration - collection-root: '' From a2ace3fb79304fd003e2de8a191d21e26517b21f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 13 Aug 2022 10:54:48 +0200 Subject: [PATCH 053/365] Add missing options for 'ip dhcp-server network'. (#106) --- changelogs/fragments/106-api-path-ip-dhcp-network.yml | 2 ++ plugins/module_utils/_api_data.py | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 changelogs/fragments/106-api-path-ip-dhcp-network.yml diff --git a/changelogs/fragments/106-api-path-ip-dhcp-network.yml b/changelogs/fragments/106-api-path-ip-dhcp-network.yml new file mode 100644 index 0000000..4cb64e4 --- /dev/null +++ b/changelogs/fragments/106-api-path-ip-dhcp-network.yml @@ -0,0 +1,2 @@ +bugfixes: + - "api_modify, api_info - make API path ``ip dhcp-server network`` support missing options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/106)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 7951fed..5d2958f 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -763,12 +763,17 @@ PATHS = { primary_keys=('address', ), fields={ 'address': KeyInfo(), + 'boot-file-name': KeyInfo(default=''), 'caps-manager': KeyInfo(default=''), 'comment': KeyInfo(can_disable=True, remove_value=''), 'dhcp-option': KeyInfo(default=''), + 'dhcp-option-set': KeyInfo(default=''), + 'dns-none': KeyInfo(default=''), 'dns-server': KeyInfo(default=''), + 'domain': KeyInfo(default=''), 'gateway': KeyInfo(automatically_computed_from=('address', )), 'netmask': KeyInfo(automatically_computed_from=('address', )), + 'next-server': KeyInfo(default=''), 'ntp-server': KeyInfo(default=''), 'wins-server': KeyInfo(default=''), }, From f797b4a231a44823e31a3f2ec257578e590f7de6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 13 Aug 2022 10:55:37 +0200 Subject: [PATCH 054/365] Support absent values. Support absent value 'all' for 'server' in /ip dhcp-server lease. (#107) --- .../fragments/107-api-path-ip-dhcp-lease.yml | 2 + plugins/module_utils/_api_data.py | 7 +- plugins/modules/api_info.py | 6 +- plugins/modules/api_modify.py | 21 +++- tests/unit/plugins/modules/fake_api.py | 5 + tests/unit/plugins/modules/test_api_info.py | 89 ++++++++++++++ tests/unit/plugins/modules/test_api_modify.py | 112 ++++++++++++++++++ 7 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 changelogs/fragments/107-api-path-ip-dhcp-lease.yml diff --git a/changelogs/fragments/107-api-path-ip-dhcp-lease.yml b/changelogs/fragments/107-api-path-ip-dhcp-lease.yml new file mode 100644 index 0000000..b421dc1 --- /dev/null +++ b/changelogs/fragments/107-api-path-ip-dhcp-lease.yml @@ -0,0 +1,2 @@ +bugfixes: + - "api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5d2958f..e7cdce6 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -46,18 +46,21 @@ class APIData(object): class KeyInfo(object): - def __init__(self, _dummy=None, can_disable=False, remove_value=None, default=None, required=False, automatically_computed_from=None): + def __init__(self, _dummy=None, can_disable=False, remove_value=None, absent_value=None, default=None, required=False, automatically_computed_from=None): if _dummy is not None: raise ValueError('KeyInfo() does not have positional arguments') if sum([required, default is not None, automatically_computed_from is not None, can_disable]) > 1: raise ValueError('required, default, automatically_computed_from, and can_disable are mutually exclusive') if not can_disable and remove_value is not None: raise ValueError('remove_value can only be specified if can_disable=True') + if absent_value is not None and any([default is not None, automatically_computed_from is not None, can_disable]): + raise ValueError('absent_value can not be combined with default, automatically_computed_from, can_disable=True, or absent_value') self.can_disable = can_disable self.remove_value = remove_value self.automatically_computed_from = automatically_computed_from self.default = default self.required = required + self.absent_value = absent_value def split_path(path): @@ -755,7 +758,7 @@ PATHS = { 'disabled': KeyInfo(default=False), 'insert-queue-before': KeyInfo(can_disable=True), 'mac-address': KeyInfo(can_disable=True, remove_value=''), - 'server': KeyInfo(), + 'server': KeyInfo(absent_value='all'), }, ), ('ip', 'dhcp-server', 'network'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 2a15bc6..75e1a00 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -275,10 +275,12 @@ def main(): if handle_disabled == 'exclamation': k = '!%s' % k entry[k] = None - if hide_defaults: - for k, field_info in path_info.fields.items(): + for k, field_info in path_info.fields.items(): + if hide_defaults: if field_info.default is not None and entry.get(k) == field_info.default: entry.pop(k) + if field_info.absent_value and k not in entry: + entry[k] = field_info.absent_value result.append(entry) module.exit_json(result=result) diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index fe7a13e..fdf682e 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -446,6 +446,15 @@ def remove_dynamic(entries): return result +def get_api_data(api_path, path_info): + entries = list(api_path) + for entry in entries: + for k, field_info in path_info.fields.items(): + if field_info.absent_value is not None and k not in entry: + entry[k] = field_info.absent_value + return entries + + def sync_list(module, api, path, path_info): handle_absent_entries = module.params['handle_absent_entries'] handle_entries_content = module.params['handle_entries_content'] @@ -476,7 +485,7 @@ def sync_list(module, api, path, path_info): api_path = compose_api_path(api, path) - old_data = list(api_path) + old_data = get_api_data(api_path, path_info) old_data = remove_dynamic(old_data) stratified_old_data = defaultdict(list) for index, entry in enumerate(old_data): @@ -588,7 +597,7 @@ def sync_list(module, api, path, path_info): # For sake of completeness, retrieve the full new data: if modify_list or create_list or reorder_list: - new_data = remove_dynamic(list(api_path)) + new_data = remove_dynamic(get_api_data(api_path, path_info)) # Remove 'irrelevant' data for entry in old_data: @@ -656,7 +665,7 @@ def sync_with_primary_keys(module, api, path, path_info): api_path = compose_api_path(api, path) - old_data = list(api_path) + old_data = get_api_data(api_path, path_info) old_data = remove_dynamic(old_data) old_data_by_key = OrderedDict() id_by_key = {} @@ -782,7 +791,7 @@ def sync_with_primary_keys(module, api, path, path_info): # For sake of completeness, retrieve the full new data: if modify_list or create_list or reorder_list: - new_data = remove_dynamic(list(api_path)) + new_data = remove_dynamic(get_api_data(api_path, path_info)) # Remove 'irrelevant' data for entry in old_data: @@ -818,7 +827,7 @@ def sync_single_value(module, api, path, path_info): api_path = compose_api_path(api, path) - old_data = list(api_path) + old_data = get_api_data(api_path, path_info) if len(old_data) != 1: module.fail_json( msg='Internal error: retrieving /{path} resulted in {count} elements. Expected exactly 1.'.format( @@ -839,7 +848,7 @@ def sync_single_value(module, api, path, path_info): except (LibRouterosError, UnicodeEncodeError) as e: module.fail_json(msg='Error while modifying: {error}'.format(error=to_native(e))) # Retrieve latest version - new_data = list(api_path) + new_data = get_api_data(api_path, path_info) if len(new_data) == 1: updated_entry = new_data[0] diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index 0a3f608..b17c088 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -128,6 +128,8 @@ def _normalize_entry(entry, path_info): if ('!%s' % key) in entry: entry.pop(key, None) del entry['!%s' % key] + if data.absent_value is not None and key in entry and entry[key] == data.absent_value: + del entry[key] def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=False): @@ -142,6 +144,9 @@ def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=Fa if key == '.id' or key in path_info.fields: continue del entry[key] + for key, data in path_info.fields.items(): + if data.absent_value is not None and key not in entry: + entry[key] = data.absent_value return values diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 2195d20..e9e0696 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -406,3 +406,92 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'dynamic': True, }, ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_absent(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + '.id': '*1', + 'address': '192.168.88.2', + 'mac-address': '11:22:33:44:55:66', + 'client-id': 'ff:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:0:1:2', + 'address-lists': '', + 'server': 'main', + 'dhcp-option': '', + 'status': 'waiting', + 'last-seen': 'never', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + 'comment': 'foo', + }, + { + '.id': '*2', + 'address': '192.168.88.3', + 'mac-address': '11:22:33:44:55:77', + 'client-id': '1:2:3:4:5:6:7', + 'address-lists': '', + 'server': 'main', + 'dhcp-option': '', + 'status': 'bound', + 'expires-after': '3d7m8s', + 'last-seen': '1m52s', + 'active-address': '192.168.88.14', + 'active-mac-address': '11:22:33:44:55:76', + 'active-client-id': '1:2:3:4:5:6:7', + 'active-server': 'main', + 'host-name': 'bar', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + }, + { + '.id': '*3', + 'address': '0.0.0.1', + 'mac-address': '00:00:00:00:00:01', + 'address-lists': '', + 'dhcp-option': '', + 'status': 'waiting', + 'last-seen': 'never', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dhcp-server lease', + 'handle_disabled': 'omit', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + '.id': '*1', + 'address': '192.168.88.2', + 'mac-address': '11:22:33:44:55:66', + 'client-id': 'ff:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:0:1:2', + 'server': 'main', + 'comment': 'foo', + }, + { + '.id': '*2', + 'address': '192.168.88.3', + 'mac-address': '11:22:33:44:55:77', + 'client-id': '1:2:3:4:5:6:7', + 'server': 'main', + }, + { + '.id': '*3', + 'address': '0.0.0.1', + 'mac-address': '00:00:00:00:00:01', + 'server': 'all', + }, + ]) diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index 5c5d4ee..2d70c43 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -93,6 +93,74 @@ START_IP_ADDRESS = [ START_IP_ADDRESS_OLD_DATA = massage_expected_result_data(START_IP_ADDRESS, ('ip', 'address')) +START_IP_DHCP_SEVER_LEASE = [ + { + '.id': '*1', + 'address': '192.168.88.2', + 'mac-address': '11:22:33:44:55:66', + 'client-id': 'ff:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:0:1:2', + 'address-lists': '', + 'server': 'main', + 'dhcp-option': '', + 'status': 'waiting', + 'last-seen': 'never', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + 'comment': 'foo', + }, + { + '.id': '*2', + 'address': '192.168.88.3', + 'mac-address': '11:22:33:44:55:77', + 'client-id': '1:2:3:4:5:6:7', + 'address-lists': '', + 'server': 'main', + 'dhcp-option': '', + 'status': 'bound', + 'expires-after': '3d7m8s', + 'last-seen': '1m52s', + 'active-address': '192.168.88.14', + 'active-mac-address': '11:22:33:44:55:76', + 'active-client-id': '1:2:3:4:5:6:7', + 'active-server': 'main', + 'host-name': 'bar', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + }, + { + '.id': '*3', + 'address': '0.0.0.1', + 'mac-address': '00:00:00:00:00:01', + 'address-lists': '', + 'dhcp-option': '', + 'status': 'waiting', + 'last-seen': 'never', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + }, + { + '.id': '*4', + 'address': '0.0.0.2', + 'mac-address': '00:00:00:00:00:02', + 'address-lists': '', + 'dhcp-option': '', + 'status': 'waiting', + 'last-seen': 'never', + 'radius': False, + 'dynamic': False, + 'blocked': False, + 'disabled': False, + }, +] + +START_IP_DHCP_SEVER_LEASE_OLD_DATA = massage_expected_result_data(START_IP_DHCP_SEVER_LEASE, ('ip', 'dhcp-server', 'lease')) + class TestRouterosApiModifyModule(ModuleTestCase): @@ -1538,3 +1606,47 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'disabled': False, }, ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dhcp-server', 'lease'), START_IP_DHCP_SEVER_LEASE, read_only=True)) + def test_absent_value(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dhcp-server lease', + 'data': [ + { + 'address': '192.168.88.2', + 'mac-address': '11:22:33:44:55:66', + 'client-id': 'ff:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:0:1:2', + 'server': 'main', + 'comment': 'foo', + }, + { + 'address': '192.168.88.3', + 'mac-address': '11:22:33:44:55:77', + 'client-id': '1:2:3:4:5:6:7', + 'server': 'main', + }, + { + 'address': '0.0.0.1', + 'mac-address': '00:00:00:00:00:01', + 'server': 'all', + }, + { + 'address': '0.0.0.2', + 'mac-address': '00:00:00:00:00:02', + 'server': 'all', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) From a642f0b9eb8dd4f0a5cd44bc532260aa147254d9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 13 Aug 2022 10:56:50 +0200 Subject: [PATCH 055/365] Prepare 2.2.1 release. --- changelogs/fragments/2.2.1.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.2.1.yml diff --git a/changelogs/fragments/2.2.1.yml b/changelogs/fragments/2.2.1.yml new file mode 100644 index 0000000..a14fc0b --- /dev/null +++ b/changelogs/fragments/2.2.1.yml @@ -0,0 +1 @@ +release_summary: Bugfix release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 443cee9..b75c486 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.2.0 +version: 2.2.1 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 615b9e6952090039410b44b1c5a287d3f0bce9cd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 20 Aug 2022 20:10:10 +0200 Subject: [PATCH 056/365] Release 2.2.1. --- CHANGELOG.rst | 14 ++++++++++++++ changelogs/changelog.yaml | 15 +++++++++++++++ .../fragments/106-api-path-ip-dhcp-network.yml | 2 -- .../fragments/107-api-path-ip-dhcp-lease.yml | 2 -- changelogs/fragments/2.2.1.yml | 1 - 5 files changed, 29 insertions(+), 5 deletions(-) delete mode 100644 changelogs/fragments/106-api-path-ip-dhcp-network.yml delete mode 100644 changelogs/fragments/107-api-path-ip-dhcp-lease.yml delete mode 100644 changelogs/fragments/2.2.1.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6042ae9..f7a18f2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,20 @@ Community RouterOS Release Notes .. contents:: Topics +v2.2.1 +====== + +Release Summary +--------------- + +Bugfix release. + +Bugfixes +-------- + +- api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107). +- api_modify, api_info - make API path ``ip dhcp-server network`` support missing options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/106). + v2.2.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 2645fa6..f6fd810 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -210,3 +210,18 @@ releases: name: api_modify namespace: '' release_date: '2022-07-31' + 2.2.1: + changes: + bugfixes: + - api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` + (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107). + - api_modify, api_info - make API path ``ip dhcp-server network`` support missing + options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, + and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, + https://github.com/ansible-collections/community.routeros/pull/106). + release_summary: Bugfix release. + fragments: + - 106-api-path-ip-dhcp-network.yml + - 107-api-path-ip-dhcp-lease.yml + - 2.2.1.yml + release_date: '2022-08-20' diff --git a/changelogs/fragments/106-api-path-ip-dhcp-network.yml b/changelogs/fragments/106-api-path-ip-dhcp-network.yml deleted file mode 100644 index 4cb64e4..0000000 --- a/changelogs/fragments/106-api-path-ip-dhcp-network.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "api_modify, api_info - make API path ``ip dhcp-server network`` support missing options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/106)." diff --git a/changelogs/fragments/107-api-path-ip-dhcp-lease.yml b/changelogs/fragments/107-api-path-ip-dhcp-lease.yml deleted file mode 100644 index b421dc1..0000000 --- a/changelogs/fragments/107-api-path-ip-dhcp-lease.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107)." diff --git a/changelogs/fragments/2.2.1.yml b/changelogs/fragments/2.2.1.yml deleted file mode 100644 index a14fc0b..0000000 --- a/changelogs/fragments/2.2.1.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix release. \ No newline at end of file From d77cd95f91b93141e6b7a1ed25c1f2d03b800cbd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 Aug 2022 08:31:42 +0200 Subject: [PATCH 057/365] Make reuse conformant (#108) * Add .license files. * Add reuse test. * Update README. * Add changelog fragment. * Normalize licenses extra sanity test. * Declare REUSE conformance. * Update README. --- .github/workflows/reuse.yml | 30 ++++++++ .reuse/dep5 | 5 ++ CHANGELOG.rst.license | 3 + README.md | 2 +- changelogs/changelog.yaml.license | 3 + changelogs/fragments/licenses.yml | 2 + tests/sanity/extra/extra-docs.json.license | 3 + tests/sanity/extra/licenses.json.license | 3 + tests/sanity/extra/licenses.py | 77 +++++++++---------- tests/sanity/extra/licenses.py.license | 3 + .../extra/no-unwanted-files.json.license | 3 + tests/sanity/extra/update-docs.json.license | 3 + tests/sanity/ignore-2.10.txt.license | 3 + tests/sanity/ignore-2.11.txt.license | 3 + tests/sanity/ignore-2.12.txt.license | 3 + tests/sanity/ignore-2.13.txt.license | 3 + tests/sanity/ignore-2.14.txt.license | 3 + tests/sanity/ignore-2.9.txt.license | 3 + .../modules/fixtures/facts/export.license | 3 + .../fixtures/facts/export_verbose.license | 3 + ...erface_print_detail_without-paging.license | 3 + ...ddress_print_detail_without-paging.license | 3 + ...ighbor_print_detail_without-paging.license | 3 + ..._route_print_detail_without-paging.license | 3 + ...ddress_print_detail_without-paging.license | 3 + ...rint_detail_without-paging_no-ipv6.license | 3 + ...stance_print_detail_without-paging.license | 3 + ...p_peer_print_detail_without-paging.license | 3 + ...-route_print_detail_without-paging.license | 3 + ...stance_print_detail_without-paging.license | 3 + ...ighbor_print_detail_without-paging.license | 3 + ...stem_identity_print_without-paging.license | 3 + ...stem_resource_print_without-paging.license | 3 + ...m_routerboard_print_without-paging.license | 3 + .../fixtures/system_package_print.license | 3 + .../fixtures/system_resource_print.license | 3 + 36 files changed, 167 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/reuse.yml create mode 100644 .reuse/dep5 create mode 100644 CHANGELOG.rst.license create mode 100644 changelogs/changelog.yaml.license create mode 100644 changelogs/fragments/licenses.yml create mode 100644 tests/sanity/extra/extra-docs.json.license create mode 100644 tests/sanity/extra/licenses.json.license create mode 100644 tests/sanity/extra/licenses.py.license create mode 100644 tests/sanity/extra/no-unwanted-files.json.license create mode 100644 tests/sanity/extra/update-docs.json.license create mode 100644 tests/sanity/ignore-2.10.txt.license create mode 100644 tests/sanity/ignore-2.11.txt.license create mode 100644 tests/sanity/ignore-2.12.txt.license create mode 100644 tests/sanity/ignore-2.13.txt.license create mode 100644 tests/sanity/ignore-2.14.txt.license create mode 100644 tests/sanity/ignore-2.9.txt.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/export.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/export_verbose.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/interface_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/ip_address_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/ip_neighbor_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/ip_route_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging_no-ipv6.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/routing_bgp_instance_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/routing_bgp_peer_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/routing_bgp_vpnv4-route_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/routing_ospf_instance_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/routing_ospf_neighbor_print_detail_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/system_identity_print_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/system_resource_print_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/facts/system_routerboard_print_without-paging.license create mode 100644 tests/unit/plugins/modules/fixtures/system_package_print.license create mode 100644 tests/unit/plugins/modules/fixtures/system_resource_print.license diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml new file mode 100644 index 0000000..c10221c --- /dev/null +++ b/.github/workflows/reuse.yml @@ -0,0 +1,30 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +name: Verify REUSE + +on: + push: + branches: [main] + pull_request: + branches: [main] + # Run CI once per day (at 05:15 UTC) + schedule: + - cron: '15 5 * * *' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install dependencies + run: | + pip install reuse + + - name: Check REUSE compliance + run: | + reuse lint diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000..0c3745e --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,5 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: changelogs/fragments/* +Copyright: Ansible Project +License: GPL-3.0-or-later diff --git a/CHANGELOG.rst.license b/CHANGELOG.rst.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/CHANGELOG.rst.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/README.md b/README.md index f198a88..779b185 100644 --- a/README.md +++ b/README.md @@ -176,4 +176,4 @@ See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/commu Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.routeros/blob/main/LICENSES/BSD-2-Clause.txt). -Most files in the collection that are not automatically generated have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s). +All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `.reuse/dep5`. This conforms to the [REUSE specification](https://reuse.software/spec/). diff --git a/changelogs/changelog.yaml.license b/changelogs/changelog.yaml.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/changelogs/changelog.yaml.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/changelogs/fragments/licenses.yml b/changelogs/fragments/licenses.yml new file mode 100644 index 0000000..a10aef8 --- /dev/null +++ b/changelogs/fragments/licenses.yml @@ -0,0 +1,2 @@ +minor_changes: + - "The collection repository conforms to the `REUSE specification `__ except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108)." diff --git a/tests/sanity/extra/extra-docs.json.license b/tests/sanity/extra/extra-docs.json.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/extra/extra-docs.json.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/licenses.json.license b/tests/sanity/extra/licenses.json.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/extra/licenses.json.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py index 4708822..127288c 100755 --- a/tests/sanity/extra/licenses.py +++ b/tests/sanity/extra/licenses.py @@ -21,29 +21,35 @@ def find_licenses(filename, relax=False): spdx_license_identifiers = [] other_license_identifiers = [] has_copyright = False - with open(filename, 'r', encoding='utf-8') as f: - for line in f: - line = line.rstrip() - if 'Copyright ' in line: - has_copyright = True - if 'Copyright: ' in line: - print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, )) - idx = line.find('SPDX-License-Identifier: ') - if idx >= 0: - spdx_license_identifiers.append(line[idx + len('SPDX-License-Identifier: '):]) - if 'GNU General Public License' in line: - if 'v3.0+' in line: - other_license_identifiers.append('GPL-3.0-or-later') - if 'version 3 or later' in line: - other_license_identifiers.append('GPL-3.0-or-later') - if 'Simplified BSD License' in line: - other_license_identifiers.append('BSD-2-Clause') - if 'Apache License 2.0' in line: - other_license_identifiers.append('Apache-2.0') - if 'PSF License' in line or 'Python-2.0' in line: - other_license_identifiers.append('PSF-2.0') - if 'MIT License' in line: - other_license_identifiers.append('MIT') + try: + with open(filename, 'r', encoding='utf-8') as f: + for line in f: + line = line.rstrip() + if 'Copyright ' in line: + has_copyright = True + if 'Copyright: ' in line: + print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, )) + if 'SPDX-FileCopyrightText: ' in line: + has_copyright = True + idx = line.find('SPDX-License-Identifier: ') + if idx >= 0: + lic_id = line[idx + len('SPDX-License-Identifier: '):] + spdx_license_identifiers.extend(lic_id.split(' OR ')) + if 'GNU General Public License' in line: + if 'v3.0+' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'version 3 or later' in line: + other_license_identifiers.append('GPL-3.0-or-later') + if 'Simplified BSD License' in line: + other_license_identifiers.append('BSD-2-Clause') + if 'Apache License 2.0' in line: + other_license_identifiers.append('Apache-2.0') + if 'PSF License' in line or 'Python-2.0' in line: + other_license_identifiers.append('PSF-2.0') + if 'MIT License' in line: + other_license_identifiers.append('MIT') + except Exception as exc: + print('%s: error while processing file: %s' % (filename, exc)) if len(set(spdx_license_identifiers)) < len(spdx_license_identifiers): print('%s: found identical SPDX-License-Identifier values' % (filename, )) if other_license_identifiers and set(other_license_identifiers) != set(spdx_license_identifiers): @@ -61,26 +67,14 @@ def main(): # The following paths are allowed to have no license identifier no_comments_allowed = [ 'changelogs/fragments/*.yml', - 'tests/sanity/extra/*.json', - 'tests/sanity/ignore-2.*.txt', - 'tests/unit/plugins/modules/fixtures/*', - 'tests/unit/plugins/modules/fixtures/facts/*', - 'LICENSES/*.txt', - 'COPYING', - ] - - # Files of this name are allowed to be empty - empty_allowed = [ - '.keep', - '__init__.py', ] # These files are completely ignored ignore_paths = [ - 'CHANGELOG.rst', - 'changelogs/changelog.yaml', - 'tests/sanity/extra/licenses.py', # The strings in find_licenses() confuse this code :-) '.ansible-test-timeout.json', + '.reuse/dep5', + 'LICENSES/*.txt', + 'COPYING', ] no_comments_allowed = [fn for pattern in no_comments_allowed for fn in glob.glob(pattern)] @@ -93,9 +87,10 @@ def main(): path = path[2:] if path in ignore_paths or path.startswith('tests/output/'): continue - if os.path.basename(path) in empty_allowed: - if os.stat(path).st_size == 0: - continue + if os.stat(path).st_size == 0: + continue + if not path.endswith('.license') and os.path.exists(path + '.license'): + path = path + '.license' valid_licenses_for_path = valid_licenses if path.startswith('plugins/') and not path.startswith(('plugins/modules/', 'plugins/module_utils/')): valid_licenses_for_path = [license for license in valid_licenses if license == 'GPL-3.0-or-later'] diff --git a/tests/sanity/extra/licenses.py.license b/tests/sanity/extra/licenses.py.license new file mode 100644 index 0000000..6c4958f --- /dev/null +++ b/tests/sanity/extra/licenses.py.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: 2022, Felix Fontein diff --git a/tests/sanity/extra/no-unwanted-files.json.license b/tests/sanity/extra/no-unwanted-files.json.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/extra/no-unwanted-files.json.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/update-docs.json.license b/tests/sanity/extra/update-docs.json.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/extra/update-docs.json.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.10.txt.license b/tests/sanity/ignore-2.10.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.10.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.11.txt.license b/tests/sanity/ignore-2.11.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.11.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.12.txt.license b/tests/sanity/ignore-2.12.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.12.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.13.txt.license b/tests/sanity/ignore-2.13.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.13.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.14.txt.license b/tests/sanity/ignore-2.14.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.14.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/ignore-2.9.txt.license b/tests/sanity/ignore-2.9.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.9.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/export.license b/tests/unit/plugins/modules/fixtures/facts/export.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/export.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/export_verbose.license b/tests/unit/plugins/modules/fixtures/facts/export_verbose.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/export_verbose.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/interface_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/interface_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/interface_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/ip_address_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/ip_address_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/ip_address_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/ip_neighbor_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/ip_neighbor_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/ip_neighbor_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/ip_route_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/ip_route_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/ip_route_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging_no-ipv6.license b/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging_no-ipv6.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/ipv6_address_print_detail_without-paging_no-ipv6.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/routing_bgp_instance_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_instance_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_instance_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/routing_bgp_peer_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_peer_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_peer_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/routing_bgp_vpnv4-route_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_vpnv4-route_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/routing_bgp_vpnv4-route_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/routing_ospf_instance_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/routing_ospf_instance_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/routing_ospf_instance_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/routing_ospf_neighbor_print_detail_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/routing_ospf_neighbor_print_detail_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/routing_ospf_neighbor_print_detail_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/system_identity_print_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/system_identity_print_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/system_identity_print_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/system_resource_print_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/system_resource_print_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/system_resource_print_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/facts/system_routerboard_print_without-paging.license b/tests/unit/plugins/modules/fixtures/facts/system_routerboard_print_without-paging.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/facts/system_routerboard_print_without-paging.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/system_package_print.license b/tests/unit/plugins/modules/fixtures/system_package_print.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/system_package_print.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/unit/plugins/modules/fixtures/system_resource_print.license b/tests/unit/plugins/modules/fixtures/system_resource_print.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/unit/plugins/modules/fixtures/system_resource_print.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From 47bbf95fa397cd3e6b090f9489b4e0951563fc78 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 Aug 2022 11:35:29 +0200 Subject: [PATCH 058/365] Fix workflow's permissions. --- .github/workflows/reuse.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index c10221c..5b25572 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -15,7 +15,9 @@ on: - cron: '15 5 * * *' jobs: - build: + check: + permissions: + contents: read runs-on: ubuntu-latest steps: From 776b599ffe4a873d1b1ff1fbbece855013784494 Mon Sep 17 00:00:00 2001 From: TobsA Date: Wed, 7 Sep 2022 21:10:11 +0200 Subject: [PATCH 059/365] Added timeout setting for api. (#109) * Added timeout setting for api. * Added changelog fragment * Added "version_added" to api doc * Added "," for better diff * Fixed case and punctuation in changelog Co-authored-by: Felix Fontein * Fixed url in changelog fragment Co-authored-by: Felix Fontein --- changelogs/fragments/109-add-timeout-parameter-to-api.yml | 2 ++ plugins/doc_fragments/api.py | 6 ++++++ plugins/module_utils/api.py | 7 +++++-- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/109-add-timeout-parameter-to-api.yml diff --git a/changelogs/fragments/109-add-timeout-parameter-to-api.yml b/changelogs/fragments/109-add-timeout-parameter-to-api.yml new file mode 100644 index 0000000..a876f68 --- /dev/null +++ b/changelogs/fragments/109-add-timeout-parameter-to-api.yml @@ -0,0 +1,2 @@ +minor_changes: +- "api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109)." diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index ddbea6d..6b92d28 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -27,6 +27,12 @@ options: - RouterOS user password. required: true type: str + timeout: + description: + - Timeout for the request. + type: int + default: 10 + version_added: 2.3.0 tls: description: - If is set TLS will be used for RouterOS API connection. diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index f4060f1..1783f9a 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -44,11 +44,12 @@ def api_argument_spec(): validate_certs=dict(type='bool', default=True), validate_cert_hostname=dict(type='bool', default=False), ca_path=dict(type='path'), - encoding=dict(type='str', default='ASCII') + encoding=dict(type='str', default='ASCII'), + timeout=dict(type='int', default=10), ) -def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding): +def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding, timeout): '''Connect to RouterOS API.''' if not port: if use_tls: @@ -62,6 +63,7 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c host=host, port=port, encoding=encoding, + timeout=timeout, ) if use_tls: ctx = ssl.create_default_context(cafile=ca_path) @@ -103,4 +105,5 @@ def create_api(module): module.params['validate_cert_hostname'], module.params['ca_path'], module.params['encoding'], + module.params['timeout'], ) From 3c0ad57eb5da2025d3056275d68c28783467755b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Sep 2022 17:25:25 +0200 Subject: [PATCH 060/365] Extend API support. (#110) --- changelogs/fragments/110-api.yml | 6 +++ plugins/module_utils/_api_data.py | 79 +++++++++++++++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 87 insertions(+) create mode 100644 changelogs/fragments/110-api.yml diff --git a/changelogs/fragments/110-api.yml b/changelogs/fragments/110-api.yml new file mode 100644 index 0000000..844cb99 --- /dev/null +++ b/changelogs/fragments/110-api.yml @@ -0,0 +1,6 @@ +bugfixes: + - api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` + (https://github.com/ansible-collections/community.routeros/pull/110). +minor_changes: + - api_modify, api_info - support API path ``ip firewall mangle`` + (https://github.com/ansible-collections/community.routeros/pull/110). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e7cdce6..fc23127 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -732,6 +732,7 @@ PATHS = { 'dhcp-options': KeyInfo(default='hostname,clientid'), 'disabled': KeyInfo(default=False), 'interface': KeyInfo(), + 'script': KeyInfo(can_disable=True), 'use-peer-dns': KeyInfo(default=True), 'use-peer-ntp': KeyInfo(default=True), }, @@ -893,6 +894,82 @@ PATHS = { 'ttl': KeyInfo(can_disable=True), }, ), + ('ip', 'firewall', 'mangle'): APIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-nat-state': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'new-connection-mark': KeyInfo(can_disable=True), + 'new-dscp': KeyInfo(can_disable=True), + 'new-mss': KeyInfo(can_disable=True), + 'new-packet-mark': KeyInfo(can_disable=True), + 'new-priority': KeyInfo(can_disable=True), + 'new-routing-mark': KeyInfo(can_disable=True), + 'new-ttl': KeyInfo(can_disable=True), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'p2p': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'passthrough': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'route-dst': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'routing-table': KeyInfo(can_disable=True), + 'sniff-id': KeyInfo(can_disable=True), + 'sniff-target': KeyInfo(can_disable=True), + 'sniff-target-port': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ('ip', 'firewall', 'nat'): APIData( fully_understood=True, stratify_keys=('chain', ), @@ -902,6 +979,8 @@ PATHS = { 'comment': KeyInfo(can_disable=True, remove_value=''), 'dst-address': KeyInfo(can_disable=True), 'dst-port': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), 'out-interface': KeyInfo(can_disable=True), 'out-interface-list': KeyInfo(can_disable=True), 'protocol': KeyInfo(can_disable=True), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 75e1a00..d580bb6 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -71,6 +71,7 @@ options: - ip firewall address-list - ip firewall connection tracking - ip firewall filter + - ip firewall mangle - ip firewall nat - ip firewall service-port - ip hotspot service-port diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index fdf682e..a0d76ba 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -73,6 +73,7 @@ options: - ip firewall address-list - ip firewall connection tracking - ip firewall filter + - ip firewall mangle - ip firewall nat - ip firewall service-port - ip hotspot service-port From fb0340c6e670487bc679c0bbfdcb9a2d1463c005 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Sep 2022 17:26:35 +0200 Subject: [PATCH 061/365] Prepare 2.3.0 release. --- changelogs/fragments/2.3.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.3.0.yml diff --git a/changelogs/fragments/2.3.0.yml b/changelogs/fragments/2.3.0.yml new file mode 100644 index 0000000..80287c3 --- /dev/null +++ b/changelogs/fragments/2.3.0.yml @@ -0,0 +1 @@ +release_summary: Feature and bugfix release. diff --git a/galaxy.yml b/galaxy.yml index b75c486..148fd75 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.2.1 +version: 2.3.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 7500dceb8e7e7abaf02584bbc993303ffa26c52f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Sep 2022 17:42:49 +0200 Subject: [PATCH 062/365] Release 2.3.0. --- CHANGELOG.rst | 20 +++++++++++++++++++ changelogs/changelog.yaml | 18 +++++++++++++++++ .../109-add-timeout-parameter-to-api.yml | 2 -- changelogs/fragments/110-api.yml | 6 ------ changelogs/fragments/2.3.0.yml | 1 - changelogs/fragments/licenses.yml | 2 -- 6 files changed, 38 insertions(+), 11 deletions(-) delete mode 100644 changelogs/fragments/109-add-timeout-parameter-to-api.yml delete mode 100644 changelogs/fragments/110-api.yml delete mode 100644 changelogs/fragments/2.3.0.yml delete mode 100644 changelogs/fragments/licenses.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f7a18f2..3d05668 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,26 @@ Community RouterOS Release Notes .. contents:: Topics +v2.3.0 +====== + +Release Summary +--------------- + +Feature and bugfix release. + +Minor Changes +------------- + +- The collection repository conforms to the `REUSE specification `__ except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108). +- api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109). +- api_modify, api_info - support API path ``ip firewall mangle`` (https://github.com/ansible-collections/community.routeros/pull/110). + +Bugfixes +-------- + +- api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` (https://github.com/ansible-collections/community.routeros/pull/110). + v2.2.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index f6fd810..44c646f 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -225,3 +225,21 @@ releases: - 107-api-path-ip-dhcp-lease.yml - 2.2.1.yml release_date: '2022-08-20' + 2.3.0: + changes: + bugfixes: + - api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, + and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` + (https://github.com/ansible-collections/community.routeros/pull/110). + minor_changes: + - The collection repository conforms to the `REUSE specification `__ + except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108). + - api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109). + - api_modify, api_info - support API path ``ip firewall mangle`` (https://github.com/ansible-collections/community.routeros/pull/110). + release_summary: Feature and bugfix release. + fragments: + - 109-add-timeout-parameter-to-api.yml + - 110-api.yml + - 2.3.0.yml + - licenses.yml + release_date: '2022-09-11' diff --git a/changelogs/fragments/109-add-timeout-parameter-to-api.yml b/changelogs/fragments/109-add-timeout-parameter-to-api.yml deleted file mode 100644 index a876f68..0000000 --- a/changelogs/fragments/109-add-timeout-parameter-to-api.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- "api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109)." diff --git a/changelogs/fragments/110-api.yml b/changelogs/fragments/110-api.yml deleted file mode 100644 index 844cb99..0000000 --- a/changelogs/fragments/110-api.yml +++ /dev/null @@ -1,6 +0,0 @@ -bugfixes: - - api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` - (https://github.com/ansible-collections/community.routeros/pull/110). -minor_changes: - - api_modify, api_info - support API path ``ip firewall mangle`` - (https://github.com/ansible-collections/community.routeros/pull/110). diff --git a/changelogs/fragments/2.3.0.yml b/changelogs/fragments/2.3.0.yml deleted file mode 100644 index 80287c3..0000000 --- a/changelogs/fragments/2.3.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature and bugfix release. diff --git a/changelogs/fragments/licenses.yml b/changelogs/fragments/licenses.yml deleted file mode 100644 index a10aef8..0000000 --- a/changelogs/fragments/licenses.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - "The collection repository conforms to the `REUSE specification `__ except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108)." From 5affbf6b058656499e5fcf76300db73d7795e491 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 21 Sep 2022 10:40:45 +0200 Subject: [PATCH 063/365] Add stable-2.14 to CI. (#112) --- .github/workflows/ansible-test.yml | 7 +++++++ .github/workflows/docs-pr.yml | 2 +- README.md | 2 +- tests/sanity/ignore-2.15.txt | 1 + tests/sanity/ignore-2.15.txt.license | 3 +++ 5 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/sanity/ignore-2.15.txt create mode 100644 tests/sanity/ignore-2.15.txt.license diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 23395cf..1c9550f 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -31,6 +31,7 @@ jobs: - stable-2.11 - stable-2.12 - stable-2.13 + - stable-2.14 - devel runs-on: ubuntu-latest steps: @@ -57,6 +58,7 @@ jobs: - stable-2.11 - stable-2.12 - stable-2.13 + - stable-2.14 - devel steps: @@ -108,6 +110,11 @@ jobs: python: 3.8 - ansible: stable-2.13 python: "3.10" + # 2.14 + - ansible: stable-2.14 + python: 3.9 + - ansible: stable-2.14 + python: "3.11" steps: - name: >- diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index ef44a68..9a587c7 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -19,7 +19,7 @@ jobs: uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main with: init-fail-on-error: true - ansible-ref: devel + ansible-ref: stable-2.14 comment: permissions: diff --git a/README.md b/README.md index 779b185..d5b538b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can find [documentation for the modules and plugins in this collection here] ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12 and ansible-core 2.13 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.15.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.15.txt.license b/tests/sanity/ignore-2.15.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.15.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From 6526588f13b19e87571b35c0e5fff37251ba719a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Sep 2022 06:38:39 +0200 Subject: [PATCH 064/365] stable-2.14 is now default. --- .github/workflows/docs-pr.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 9a587c7..84adc61 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -19,7 +19,6 @@ jobs: uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main with: init-fail-on-error: true - ansible-ref: stable-2.14 comment: permissions: From bbcd9fecef8ffee94a886c2100a1608653a7b3fc Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 17 Oct 2022 22:51:58 +0200 Subject: [PATCH 065/365] Bump GHA checkout version (#116) * Bump checkout version. * Also update actions/setup-python actions. --- .github/workflows/ee.yml | 2 +- .github/workflows/extra-tests.yml | 2 +- .github/workflows/import-galaxy.yml | 4 ++-- .github/workflows/reuse.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 8d005f4..bc85932 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -38,7 +38,7 @@ jobs: path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.10' diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index a4fe4b5..0bbcdbb 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -31,7 +31,7 @@ jobs: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.10' diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index 47b0db3..55a7310 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -28,7 +28,7 @@ jobs: path: ./checkout - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.10' @@ -69,7 +69,7 @@ jobs: - build-collection steps: - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.10' diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 5b25572..acd7bc8 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install dependencies run: | From 29b604464a2312936519a541bbdee368b4a5f77a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 17 Oct 2022 22:57:35 +0200 Subject: [PATCH 066/365] Use dependabot to update GHAs. --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..2f4ff90 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From 835cec5e24bbf8d0e3dc86e936fc9b89a023d29c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 6 Nov 2022 20:58:06 +0100 Subject: [PATCH 067/365] Use attributes to document module capabilities; warn about command module's check_mode support (#118) * Improve formatting. * Add 'api' action group attribute. * Document attributes. * Known issue: command module declares to support check mode. * Compatibility with older ansible-core releases. * Fix typo. * Improve docs. * Add shortcuts for common combinations. * Update changelogs/fragments/command-check_mode.yml Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com> Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com> --- changelogs/fragments/command-check_mode.yml | 4 + docs/docsite/rst/api-guide.rst | 4 +- meta/runtime.yml | 10 +-- plugins/doc_fragments/attributes.py | 98 +++++++++++++++++++++ plugins/modules/api.py | 13 ++- plugins/modules/api_facts.py | 8 ++ plugins/modules/api_find_and_modify.py | 11 ++- plugins/modules/api_info.py | 9 +- plugins/modules/api_modify.py | 12 ++- plugins/modules/command.py | 15 ++++ plugins/modules/facts.py | 8 ++ 11 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 changelogs/fragments/command-check_mode.yml create mode 100644 plugins/doc_fragments/attributes.py diff --git a/changelogs/fragments/command-check_mode.yml b/changelogs/fragments/command-check_mode.yml new file mode 100644 index 0000000..6f2ae31 --- /dev/null +++ b/changelogs/fragments/command-check_mode.yml @@ -0,0 +1,4 @@ +known_issues: + - "The ``community.routeros.command`` module claims to support check mode. + Since it cannot judge whether the commands executed modify state or not, this behavior is incorrect. + Since this potentially breaks existing playbooks, we will not change this behavior until community.routeros 3.0.0." diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index a96d84c..92a9674 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -17,7 +17,7 @@ No special setup is needed; the module needs to be run on a host that can connec --- - name: RouterOS test with API hosts: localhost - gather_facts: no + gather_facts: false vars: hostname: 192.168.1.1 username: admin @@ -71,7 +71,7 @@ To avoid having to specify common parameters for all the API based modules in ev --- - name: RouterOS test with API hosts: localhost - gather_facts: no + gather_facts: false module_defaults: group/community.routeros.api hostname: 192.168.1.1 diff --git a/meta/runtime.yml b/meta/runtime.yml index c9cdbbf..5aafd31 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -6,8 +6,8 @@ requires_ansible: '>=2.9.10' action_groups: api: - - api - - api_facts - - api_find_and_modify - - api_info - - api_modify + - api + - api_facts + - api_find_and_modify + - api_info + - api_modify diff --git a/plugins/doc_fragments/attributes.py b/plugins/doc_fragments/attributes.py new file mode 100644 index 0000000..e18a48f --- /dev/null +++ b/plugins/doc_fragments/attributes.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + + # Standard documentation fragment + DOCUMENTATION = r''' +options: {} +attributes: + check_mode: + description: Can run in C(check_mode) and return changed status prediction without modifying target. + diff_mode: + description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode. + platform: + description: Target OS/families that can be operated against. + support: N/A +''' + + # Should be used together with the standard fragment + INFO_MODULE = r''' +options: {} +attributes: + check_mode: + support: full + details: + - This action does not modify state. + diff_mode: + support: N/A + details: + - This action does not modify state. +''' + + ACTIONGROUP_API = r''' +options: {} +attributes: + action_group: + description: Use C(group/community.routeros.api) in C(module_defaults) to set defaults for this module. + support: full + membership: + - community.routeros.api +''' + + CONN = r''' +options: {} +attributes: + become: + description: Is usable alongside C(become) keywords. + connection: + description: Uses the target's configured connection information to execute code on it. + delegation: + description: Can be used in conjunction with C(delegate_to) and related keywords. +''' + + FACTS = r''' +options: {} +attributes: + facts: + description: Action returns an C(ansible_facts) dictionary that will update existing host facts. +''' + + # Should be used together with the standard fragment and the FACTS fragment + FACTS_MODULE = r''' +options: {} +attributes: + check_mode: + support: full + details: + - This action does not modify state. + diff_mode: + support: N/A + details: + - This action does not modify state. + facts: + support: full +''' + + FILES = r''' +options: {} +attributes: + safe_file_operations: + description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption. +''' + + FLOW = r''' +options: {} +attributes: + action: + description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller. + async: + description: Supports being used with the C(async) keyword. +''' diff --git a/plugins/modules/api.py b/plugins/modules/api.py index ea667a5..dbf9d3d 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -18,12 +18,23 @@ description: - This module can add, remove, update, query and execute arbitrary command in RouterOS via API. notes: - I(add), I(remove), I(update), I(cmd) and I(query) are mutually exclusive. - - I(check_mode) is not supported. - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules for more specific modifications, and the M(community.routeros.api_info) module for a more controlled way of returning all entries for a path. extends_documentation_fragment: - community.routeros.api + - community.routeros.attributes + - community.routeros.attributes.actiongroup_api +attributes: + check_mode: + support: none + diff_mode: + support: none + platform: + support: full + platforms: RouterOS + action_group: + version_added: 2.1.0 options: path: description: diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 7db910c..59de196 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -28,6 +28,14 @@ description: RouterOS API, similar to the M(community.routeros.api) module. extends_documentation_fragment: - community.routeros.api + - community.routeros.attributes + - community.routeros.attributes.actiongroup_api + - community.routeros.attributes.facts + - community.routeros.attributes.facts_module +attributes: + platform: + support: full + platforms: RouterOS options: gather_subset: description: diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index a3b61f0..0be3f70 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -24,9 +24,18 @@ notes: there are at least N such values, you can use I(require_matches_min=N) together with I(allow_no_matches=true). This will make the module fail if there are less than N such entries, but not if there is no match. The latter case is needed for idempotency of the task: once the values have been changed, there should be no further match." - - Supports I(check_mode). extends_documentation_fragment: - community.routeros.api + - community.routeros.attributes + - community.routeros.attributes.actiongroup_api +attributes: + check_mode: + support: full + diff_mode: + support: full + platform: + support: full + platforms: RouterOS options: path: description: diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index d580bb6..bf1b23f 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -24,10 +24,15 @@ description: - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). -notes: - - Supports I(check_mode). extends_documentation_fragment: - community.routeros.api + - community.routeros.attributes + - community.routeros.attributes.actiongroup_api + - community.routeros.attributes.info_module +attributes: + platform: + support: full + platforms: RouterOS options: path: description: diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index a0d76ba..9e73c91 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -24,12 +24,20 @@ description: - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). -notes: - - Supports I(check_mode). requirements: - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6 extends_documentation_fragment: - community.routeros.api + - community.routeros.attributes + - community.routeros.attributes.actiongroup_api +attributes: + check_mode: + support: full + diff_mode: + support: full + platform: + support: full + platforms: RouterOS options: path: description: diff --git a/plugins/modules/command.py b/plugins/modules/command.py index c96e153..83cd776 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -20,6 +20,21 @@ description: - The module always indicates a (changed) status. You can use R(the changed_when task property,override_the_changed_result) to determine whether a command task actually resulted in a change or not. +notes: + - The module declares that it B(supports check mode). This is a bug and will + be changed in community.routeros 3.0.0. +extends_documentation_fragment: + - community.routeros.attributes +attributes: + check_mode: + support: partial + details: + - The module claims to support check mode, but it simply always executes the command. + diff_mode: + support: none + platform: + support: full + platforms: RouterOS options: commands: description: diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index cefaf5c..7b1cd0d 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -18,6 +18,14 @@ description: base network fact keys with C(ansible_net_). The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. +extends_documentation_fragment: + - community.routeros.attributes + - community.routeros.attributes.facts + - community.routeros.attributes.facts_module +attributes: + platform: + support: full + platforms: RouterOS options: gather_subset: description: From fc0d483848a818a05f3144ee4826bf55d6bccb12 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 6 Nov 2022 20:59:44 +0100 Subject: [PATCH 068/365] Prepare 2.3.1 release. --- changelogs/fragments/2.3.1.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.3.1.yml diff --git a/changelogs/fragments/2.3.1.yml b/changelogs/fragments/2.3.1.yml new file mode 100644 index 0000000..3f8a446 --- /dev/null +++ b/changelogs/fragments/2.3.1.yml @@ -0,0 +1 @@ +release_summary: Maintenance release with improved documentation. diff --git a/galaxy.yml b/galaxy.yml index 148fd75..020681e 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.3.0 +version: 2.3.1 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 3b3d2171b427082d00d8f8456d4ec1195e19c0e5 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 6 Nov 2022 22:02:28 +0100 Subject: [PATCH 069/365] Release 2.3.1. --- CHANGELOG.rst | 13 +++++++++++++ changelogs/changelog.yaml | 12 ++++++++++++ changelogs/fragments/2.3.1.yml | 1 - changelogs/fragments/command-check_mode.yml | 4 ---- 4 files changed, 25 insertions(+), 5 deletions(-) delete mode 100644 changelogs/fragments/2.3.1.yml delete mode 100644 changelogs/fragments/command-check_mode.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3d05668..c4c573c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,19 @@ Community RouterOS Release Notes .. contents:: Topics +v2.3.1 +====== + +Release Summary +--------------- + +Maintenance release with improved documentation. + +Known Issues +------------ + +- The ``community.routeros.command`` module claims to support check mode. Since it cannot judge whether the commands executed modify state or not, this behavior is incorrect. Since this potentially breaks existing playbooks, we will not change this behavior until community.routeros 3.0.0. + v2.3.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 44c646f..d3615e6 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -243,3 +243,15 @@ releases: - 2.3.0.yml - licenses.yml release_date: '2022-09-11' + 2.3.1: + changes: + known_issues: + - The ``community.routeros.command`` module claims to support check mode. Since + it cannot judge whether the commands executed modify state or not, this behavior + is incorrect. Since this potentially breaks existing playbooks, we will not + change this behavior until community.routeros 3.0.0. + release_summary: Maintenance release with improved documentation. + fragments: + - 2.3.1.yml + - command-check_mode.yml + release_date: '2022-11-06' diff --git a/changelogs/fragments/2.3.1.yml b/changelogs/fragments/2.3.1.yml deleted file mode 100644 index 3f8a446..0000000 --- a/changelogs/fragments/2.3.1.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Maintenance release with improved documentation. diff --git a/changelogs/fragments/command-check_mode.yml b/changelogs/fragments/command-check_mode.yml deleted file mode 100644 index 6f2ae31..0000000 --- a/changelogs/fragments/command-check_mode.yml +++ /dev/null @@ -1,4 +0,0 @@ -known_issues: - - "The ``community.routeros.command`` module claims to support check mode. - Since it cannot judge whether the commands executed modify state or not, this behavior is incorrect. - Since this potentially breaks existing playbooks, we will not change this behavior until community.routeros 3.0.0." From c2e58c3ae47630a1d3df2dd77cf71cdc275e39bd Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Wed, 9 Nov 2022 21:10:25 +0100 Subject: [PATCH 070/365] Interface list (#120) * interface list & member Signed-off-by: Tomas Herfert * adding changelog fragment Signed-off-by: Tomas Herfert * changelog fix Signed-off-by: Tomas Herfert * sanity fix Signed-off-by: Tomas Herfert * Apply suggestions from code review Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/120-api.yml | 3 +++ plugins/module_utils/_api_data.py | 11 +++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 18 insertions(+) create mode 100644 changelogs/fragments/120-api.yml diff --git a/changelogs/fragments/120-api.yml b/changelogs/fragments/120-api.yml new file mode 100644 index 0000000..61fbe3b --- /dev/null +++ b/changelogs/fragments/120-api.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API paths ``interface list`` and ``interface list member`` + (https://github.com/ansible-collections/community.routeros/pull/120). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fc23127..5ba3e26 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -132,6 +132,7 @@ PATHS = { ), ('interface', 'list'): APIData( primary_keys=('name', ), + fully_understood=True, fields={ 'comment': KeyInfo(can_disable=True, remove_value=''), 'exclude': KeyInfo(), @@ -139,6 +140,16 @@ PATHS = { 'name': KeyInfo(), }, ), + ('interface', 'list', 'member'): APIData( + primary_keys=('list', 'interface', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'interface': KeyInfo(), + 'list': KeyInfo(), + 'disabled': KeyInfo(default=False), + }, + ), ('interface', 'lte', 'apn'): APIData( unknown_mechanism=True, # primary_keys=('default', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index bf1b23f..b7db465 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -53,6 +53,8 @@ options: - interface ethernet switch - interface ethernet switch port - interface l2tp-server server + - interface list + - interface list member - interface ovpn-server server - interface pptp-server server - interface sstp-server server diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 9e73c91..5b3fc15 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -58,6 +58,8 @@ options: - interface ethernet switch - interface ethernet switch port - interface l2tp-server server + - interface list + - interface list member - interface ovpn-server server - interface pptp-server server - interface sstp-server server From 1e36dfa2d03957d5311ce5d63e7c838e9378cbb8 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Thu, 10 Nov 2022 21:09:03 +0100 Subject: [PATCH 071/365] adding "system ntp *" paths related to ROS7 (#122) * adding "system ntp *" paths related to ROS7 Signed-off-by: Tomas Herfert * changelog Signed-off-by: Tomas Herfert * docs Signed-off-by: Tomas Herfert * typo Signed-off-by: Tomas Herfert * sanity fix Signed-off-by: Tomas Herfert * setting the correct defaults Signed-off-by: Tomas Herfert * Apply suggestions from code review Co-authored-by: Felix Fontein * typo Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/122-api.yml | 4 ++++ plugins/module_utils/_api_data.py | 31 +++++++++++++++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 39 insertions(+) create mode 100644 changelogs/fragments/122-api.yml diff --git a/changelogs/fragments/122-api.yml b/changelogs/fragments/122-api.yml new file mode 100644 index 0000000..399dabe --- /dev/null +++ b/changelogs/fragments/122-api.yml @@ -0,0 +1,4 @@ +minor_changes: + - api_modify, api_info - support paths ``system ntp client servers`` and ``system ntp server`` available in ROS7, + as well as new fields ``servers``, ``mode``, and ``vrf`` for ``system ntp client`` + (https://github.com/ansible-collections/community.routeros/pull/122). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5ba3e26..fbaa9c3 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1487,6 +1487,37 @@ PATHS = { 'primary-ntp': KeyInfo(default='0.0.0.0'), 'secondary-ntp': KeyInfo(default='0.0.0.0'), 'server-dns-names': KeyInfo(default=''), + 'servers': KeyInfo(default=''), + 'mode': KeyInfo(default='unicast'), + 'vrf': KeyInfo(default='main'), + }, + ), + ('system', 'ntp', 'client', 'servers'): APIData( + primary_keys=('address', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'address': KeyInfo(), + 'auth-key': KeyInfo(default='none'), + 'iburst': KeyInfo(default=True), + 'max-poll': KeyInfo(default=10), + 'min-poll': KeyInfo(default=6), + }, + ), + ('system', 'ntp', 'server'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'auth-key': KeyInfo(default='none'), + 'broadcast': KeyInfo(default=False), + 'broadcast-addresses': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'local-clock-stratum': KeyInfo(default=5), + 'manycast': KeyInfo(default=False), + 'multicast': KeyInfo(default=False), + 'use-local-clock': KeyInfo(default=False), + 'vrf': KeyInfo(default='main'), }, ), ('system', 'package', 'update'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index b7db465..a297d63 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -117,6 +117,8 @@ options: - system leds settings - system note - system ntp client + - system ntp client servers + - system ntp server - system package update - system routerboard settings - system upgrade mirror diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 5b3fc15..a77fdc1 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -122,6 +122,8 @@ options: - system leds settings - system note - system ntp client + - system ntp client servers + - system ntp server - system package update - system routerboard settings - system upgrade mirror From 558eb501d28a4b86998edb7697aac7b27414acc7 Mon Sep 17 00:00:00 2001 From: PhiBo Date: Thu, 10 Nov 2022 21:09:58 +0100 Subject: [PATCH 072/365] Add support for ip route and ip route vrf (#123) * Add support for ip route and ip route vrf * Changelog --- changelogs/fragments/123-api.yml | 3 +++ plugins/module_utils/_api_data.py | 25 +++++++++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 32 insertions(+) create mode 100644 changelogs/fragments/123-api.yml diff --git a/changelogs/fragments/123-api.yml b/changelogs/fragments/123-api.yml new file mode 100644 index 0000000..561a6ed --- /dev/null +++ b/changelogs/fragments/123-api.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` + (https://github.com/ansible-collections/community.routeros/pull/123). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fbaa9c3..88429bf 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -298,6 +298,31 @@ PATHS = { 'ranges': KeyInfo(), }, ), + ('ip', 'route'): APIData( + fully_understood=True, + fields={ + 'check-gateway': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'distance': KeyInfo(), + 'dst-address': KeyInfo(), + 'gateway': KeyInfo(required=True), + 'route-tag': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'scope': KeyInfo(), + 'target-scope': KeyInfo(), + }, + ), + ('ip', 'route', 'vrf'): APIData( + fully_understood=True, + primary_keys=('routing-mark', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interfaces': KeyInfo(), + 'routing-mark': KeyInfo(), + }, + ), ('ip', 'dhcp-server'): APIData( fully_understood=True, primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index a297d63..8baa418 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -86,6 +86,8 @@ options: - ip neighbor discovery-settings - ip pool - ip proxy + - ip route + - ip route vrf - ip service - ip settings - ip smb diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index a77fdc1..b657f9f 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -91,6 +91,8 @@ options: - ip neighbor discovery-settings - ip pool - ip proxy + - ip route + - ip route vrf - ip service - ip settings - ip smb From 9fc22be18656961c7f985c48d7909077f294dba9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 10 Nov 2022 21:10:24 +0100 Subject: [PATCH 073/365] api_modify, api_info: support more fields in existing paths (#121) * Support more paths. * Forgot comma. * Adjust tests. * power-cycle-ping-address and power-cycle-ping-timeout can be unset Co-authored-by: Tomas Herfert <68421396+therfert@users.noreply.github.com> Co-authored-by: Tomas Herfert <68421396+therfert@users.noreply.github.com> --- changelogs/fragments/121-api.yml | 6 ++++++ plugins/module_utils/_api_data.py | 12 ++++++++++++ tests/unit/plugins/modules/test_api_info.py | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/121-api.yml diff --git a/changelogs/fragments/121-api.yml b/changelogs/fragments/121-api.yml new file mode 100644 index 0000000..0452551 --- /dev/null +++ b/changelogs/fragments/121-api.yml @@ -0,0 +1,6 @@ +minor_changes: + - api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, ``mdix-enable``, ``poe-out``, ``poe-priority``, + ``poe-voltage``, ``power-cycle-interval``, ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` + for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). + - api_modify, api_info - support field ``hw-offload`` for path ``ip firewall filter`` + (https://github.com/ansible-collections/community.routeros/pull/121). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 88429bf..aa63a64 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -113,16 +113,27 @@ PATHS = { 'arp-timeout': KeyInfo(default='auto'), 'auto-negotiation': KeyInfo(default=True), 'bandwidth': KeyInfo(default='unlimited/unlimited'), + 'combo-mode': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), + 'fec-mode': KeyInfo(can_disable=True), 'full-duplex': KeyInfo(default=True), 'l2mtu': KeyInfo(default=1598), 'loop-protect': KeyInfo(default='default'), 'loop-protect-disable-time': KeyInfo(default='5m'), 'loop-protect-send-interval': KeyInfo(default='5s'), 'mac-address': KeyInfo(), + 'mdix-enable': KeyInfo(), 'mtu': KeyInfo(default=1500), 'name': KeyInfo(), 'orig-mac-address': KeyInfo(), + 'poe-out': KeyInfo(can_disable=True), + 'poe-priority': KeyInfo(can_disable=True), + 'poe-voltage': KeyInfo(can_disable=True), + 'power-cycle-interval': KeyInfo(), + 'power-cycle-ping-address': KeyInfo(can_disable=True), + 'power-cycle-ping-enabled': KeyInfo(), + 'power-cycle-ping-timeout': KeyInfo(can_disable=True), 'rx-flow-control': KeyInfo(default='off'), 'sfp-rate-select': KeyInfo(default='high'), 'sfp-shutdown-temperature': KeyInfo(default='95C'), @@ -890,6 +901,7 @@ PATHS = { 'dst-port': KeyInfo(can_disable=True), 'fragment': KeyInfo(can_disable=True), 'hotspot': KeyInfo(can_disable=True), + 'hw-offload': KeyInfo(can_disable=True), 'icmp-options': KeyInfo(can_disable=True), 'in-bridge-port': KeyInfo(can_disable=True), 'in-bridge-port-list': KeyInfo(can_disable=True), diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index e9e0696..70a5ab6 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -212,6 +212,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): '!dst-port': None, '!fragment': None, '!hotspot': None, + '!hw-offload': None, '!icmp-options': None, '!in-bridge-port': None, '!in-bridge-port-list': None, @@ -295,6 +296,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'dst-port': None, 'fragment': None, 'hotspot': None, + 'hw-offload': None, 'icmp-options': None, 'in-bridge-port': None, 'in-bridge-port-list': None, From 78d8cfb1adda2305dd36f78c3f0fdf10ccd26aae Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 10 Nov 2022 21:12:40 +0100 Subject: [PATCH 074/365] Prepare 2.4.0 release. --- changelogs/fragments/2.4.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.4.0.yml diff --git a/changelogs/fragments/2.4.0.yml b/changelogs/fragments/2.4.0.yml new file mode 100644 index 0000000..5180a2f --- /dev/null +++ b/changelogs/fragments/2.4.0.yml @@ -0,0 +1 @@ +release_summary: Feature release improving the ``api*`` modules. diff --git a/galaxy.yml b/galaxy.yml index 020681e..2722bae 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.3.1 +version: 2.4.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 9567bbf292c31cc982735e2e9072717b1181e191 Mon Sep 17 00:00:00 2001 From: PhiBo Date: Sat, 12 Nov 2022 09:47:52 +0100 Subject: [PATCH 075/365] Add new api option force_no_cert (#124) * Add new option force_no_cert Connect to a router without a certificate by using ADH ciphers. This can be useful when setting up a device. * Changelog * Update plugins/doc_fragments/api.py Co-authored-by: Felix Fontein * Update changelogs/fragments/124-api.yml Co-authored-by: Felix Fontein Co-authored-by: Felix Fontein --- README.md | 1 + changelogs/fragments/124-api.yml | 3 +++ docs/docsite/rst/api-guide.rst | 1 + plugins/doc_fragments/api.py | 11 +++++++++++ plugins/module_utils/api.py | 9 +++++++-- 5 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/124-api.yml diff --git a/README.md b/README.md index d5b538b..379ae21 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ Example playbook: password: "{{ password }}" username: "{{ username }}" tls: true + force_no_cert: false validate_certs: true validate_cert_hostname: true ca_path: /path/to/ca-certificate.pem diff --git a/changelogs/fragments/124-api.yml b/changelogs/fragments/124-api.yml new file mode 100644 index 0000000..6299cea --- /dev/null +++ b/changelogs/fragments/124-api.yml @@ -0,0 +1,3 @@ +minor_changes: + - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers + (https://github.com/ansible-collections/community.routeros/pull/124). diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index 92a9674..f3bb629 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -107,6 +107,7 @@ Setting up encryption It is recommended to always use ``tls: true`` when connecting with the API, even if you are only connecting to the device through a trusted network. The following options control how TLS/SSL is used: +:force_no_cert: Setting to ``true`` connects to the device without a certificate. **This is discouraged to use in production and is susceptible to Man-in-the-Middle attacks**, but might be useful when setting the device up. The default value is ``false``. :validate_certs: Setting to ``false`` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is ``true``. :validate_cert_hostname: Setting to ``false`` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to ``true``; the default ``false`` is chosen for backwards compatibility to an older version of the module. :ca_path: If you are not using a commerically trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate. diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index 6b92d28..dea374b 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -46,6 +46,17 @@ options: - RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection. - Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API. type: int + force_no_cert: + description: + - Set to C(true) to connect without a certificate when I(tls=true). + - See also I(validate_certs). + - B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible + to Man-in-the-Middle attacks, because the keys used in the exchange are not authenticated. + Instead of simply connecting without a certificate to "make things work" have a look at + I(validate_certs) and I(ca_path). + type: bool + default: false + version_added: 2.4.0 validate_certs: description: - Set to C(false) to skip validation of TLS certificates. diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 1783f9a..6ffa1a5 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -41,6 +41,7 @@ def api_argument_spec(): hostname=dict(type='str', required=True), port=dict(type='int'), tls=dict(type='bool', default=False, aliases=['ssl']), + force_no_cert=dict(type='bool', default=False), validate_certs=dict(type='bool', default=True), validate_cert_hostname=dict(type='bool', default=False), ca_path=dict(type='path'), @@ -49,7 +50,7 @@ def api_argument_spec(): ) -def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding, timeout): +def _ros_api_connect(module, username, password, host, port, use_tls, force_no_cert, validate_certs, validate_cert_hostname, ca_path, encoding, timeout): '''Connect to RouterOS API.''' if not port: if use_tls: @@ -68,7 +69,10 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c if use_tls: ctx = ssl.create_default_context(cafile=ca_path) wrap_context = ctx.wrap_socket - if not validate_certs: + if force_no_cert: + ctx.check_hostname = False + ctx.set_ciphers("ADH:@SECLEVEL=0") + elif not validate_certs: ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE elif not validate_cert_hostname: @@ -101,6 +105,7 @@ def create_api(module): module.params['hostname'], module.params['port'], module.params['tls'], + module.params['force_no_cert'], module.params['validate_certs'], module.params['validate_cert_hostname'], module.params['ca_path'], From ad9d7c3829ea94fe4f6a7e6c99a20a60f88c5d3f Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Sat, 12 Nov 2022 16:08:25 +0100 Subject: [PATCH 076/365] Support for additional API paths (#125) * adding api path interface pppoe-client Signed-off-by: Tomas Herfert * support for api path interface vlan Signed-off-by: Tomas Herfert * support for api path interface bridge vlan Signed-off-by: Tomas Herfert * PR ID update Signed-off-by: Tomas Herfert * typo fix Signed-off-by: Tomas Herfert * support for API path interface bridge and update of interface bridge port ingress-filtering to True Signed-off-by: Tomas Herfert * Apply suggestion per code review Signed-off-by: Tomas Herfert * Update changelogs/fragments/125-api.yml Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/125-api.yml | 6 +++ plugins/module_utils/_api_data.py | 67 +++++++++++++++++++++++++++++-- plugins/modules/api_info.py | 4 ++ plugins/modules/api_modify.py | 4 ++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/125-api.yml diff --git a/changelogs/fragments/125-api.yml b/changelogs/fragments/125-api.yml new file mode 100644 index 0000000..582623e --- /dev/null +++ b/changelogs/fragments/125-api.yml @@ -0,0 +1,6 @@ +minor_changes: + - api_modify, api_info - support API paths ``interface pppoe-client``, ``interface vlan``, ``interface bridge``, ``interface bridge vlan`` + (https://github.com/ansible-collections/community.routeros/pull/125). +bugfixes: + - api_modify, api_info - the default of the field ``ingress-filtering`` in ``interface bridge port`` is now ``true``, which is the default in ROS + (https://github.com/ansible-collections/community.routeros/pull/125). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index aa63a64..2e9572c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -79,25 +79,29 @@ def join_path(path): PATHS = { ('interface', 'bridge'): APIData( - # fully_understood=True, + fully_understood=True, primary_keys=('name', ), fields={ - 'admin-mac': KeyInfo(), + 'admin-mac': KeyInfo(default=''), 'ageing-time': KeyInfo(default='5m'), 'arp': KeyInfo(default='enabled'), 'arp-timeout': KeyInfo(default='auto'), - 'auto-mac': KeyInfo(default=False), + 'auto-mac': KeyInfo(default=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'dhcp-snooping': KeyInfo(default=False), 'disabled': KeyInfo(default=False), + 'ether-type': KeyInfo(default='0x8100'), 'fast-forward': KeyInfo(default=True), + 'frame-types': KeyInfo(default='admit-all'), 'forward-delay': KeyInfo(default='15s'), 'igmp-snooping': KeyInfo(default=False), + 'ingress-filtering': KeyInfo(default=True), 'max-message-age': KeyInfo(default='20s'), 'mtu': KeyInfo(default='auto'), 'name': KeyInfo(), 'priority': KeyInfo(default='0x8000'), 'protocol-mode': KeyInfo(default='rstp'), + 'pvid': KeyInfo(default=1), 'transmit-hold-count': KeyInfo(default=6), 'vlan-filtering': KeyInfo(default=False), }, @@ -173,6 +177,49 @@ PATHS = { 'use-peer-dns': KeyInfo(), }, ), + ('interface', 'pppoe-client'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'ac-name': KeyInfo(default=''), + 'add-default-route': KeyInfo(default=False), + 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dial-on-demand': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'host-uniq': KeyInfo(can_disable=True), + 'interface': KeyInfo(required=True), + 'keepalive-timeout': KeyInfo(default=10), + 'max-mru': KeyInfo(default='auto'), + 'max-mtu': KeyInfo(default='auto'), + 'mrru': KeyInfo(default='disabled'), + 'name': KeyInfo(), + 'password': KeyInfo(default=''), + 'profile': KeyInfo(default='default'), + 'service-name': KeyInfo(default=''), + 'use-peer-dns': KeyInfo(default=False), + 'user': KeyInfo(default=''), + }, + ), + ('interface', 'vlan'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'use-service-tag': KeyInfo(default=False), + 'vlan-id': KeyInfo(required=True), + }, + ), ('interface', 'wireless', 'security-profiles'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -486,7 +533,7 @@ PATHS = { 'frame-types': KeyInfo(default='admit-all'), 'horizon': KeyInfo(default='none'), 'hw': KeyInfo(default=True), - 'ingress-filtering': KeyInfo(default=False), + 'ingress-filtering': KeyInfo(default=True), 'interface': KeyInfo(), 'internal-path-cost': KeyInfo(default=10), 'learn': KeyInfo(default='auto'), @@ -531,6 +578,18 @@ PATHS = { 'use-ip-firewall-for-vlan': KeyInfo(default=False), }, ), + ('interface', 'bridge', 'vlan'): APIData( + fully_understood=True, + primary_keys=('bridge', 'vlan-ids', ), + fields={ + 'bridge': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'tagged': KeyInfo(default=''), + 'untagged': KeyInfo(default=''), + 'vlan-ids': KeyInfo(), + }, + ), ('ip', 'firewall', 'connection', 'tracking'): APIData( single_value=True, fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 8baa418..5cc5075 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -44,10 +44,12 @@ options: # BEGIN PATH LIST - caps-man aaa - certificate settings + - interface bridge - interface bridge port - interface bridge port-controller - interface bridge port-extender - interface bridge settings + - interface bridge vlan - interface detect-internet - interface ethernet - interface ethernet switch @@ -56,8 +58,10 @@ options: - interface list - interface list member - interface ovpn-server server + - interface pppoe-client - interface pptp-server server - interface sstp-server server + - interface vlan - interface wireless align - interface wireless cap - interface wireless sniffer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index b657f9f..d83cc70 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -49,10 +49,12 @@ options: # BEGIN PATH LIST - caps-man aaa - certificate settings + - interface bridge - interface bridge port - interface bridge port-controller - interface bridge port-extender - interface bridge settings + - interface bridge vlan - interface detect-internet - interface ethernet - interface ethernet switch @@ -61,8 +63,10 @@ options: - interface list - interface list member - interface ovpn-server server + - interface pppoe-client - interface pptp-server server - interface sstp-server server + - interface vlan - interface wireless align - interface wireless cap - interface wireless sniffer From 60427fff5e91d16e397b3cfc64785afc5d00f7d2 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Sat, 12 Nov 2022 16:09:34 +0100 Subject: [PATCH 077/365] Capsman API paths (#126) * api path support: caps-man datapath Signed-off-by: Tomas Herfert * api path support: caps-man security Signed-off-by: Tomas Herfert * api path support: caps-man configuration Signed-off-by: Tomas Herfert * api path support: caps-man access-list Signed-off-by: Tomas Herfert * api path support: caps-man manager Signed-off-by: Tomas Herfert * api path support: caps-man provisioning Signed-off-by: Tomas Herfert * docs & changelog Signed-off-by: Tomas Herfert * yamllint fix Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert --- changelogs/fragments/126-api-capsman.yml | 3 + plugins/module_utils/_api_data.py | 144 +++++++++++++++++++++++ plugins/modules/api_info.py | 6 + plugins/modules/api_modify.py | 6 + 4 files changed, 159 insertions(+) create mode 100644 changelogs/fragments/126-api-capsman.yml diff --git a/changelogs/fragments/126-api-capsman.yml b/changelogs/fragments/126-api-capsman.yml new file mode 100644 index 0000000..9dae1f8 --- /dev/null +++ b/changelogs/fragments/126-api-capsman.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man provisioning``, ``caps-man security`` + (https://github.com/ansible-collections/community.routeros/pull/126). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 2e9572c..17acb29 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -499,6 +499,114 @@ PATHS = { 'mac-mode': KeyInfo(default='as-username'), }, ), + ('caps-man', 'access-list'): APIData( + fully_understood=True, + fields={ + 'action': KeyInfo(can_disable=True), + 'allow-signal-out-of-range': KeyInfo(can_disable=True), + 'ap-tx-limit': KeyInfo(can_disable=True), + 'client-to-client-forwarding': KeyInfo(can_disable=True), + 'client-tx-limit': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(), + 'interface': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True), + 'mac-address-mask': KeyInfo(can_disable=True), + 'private-passphrase': KeyInfo(can_disable=True), + 'radius-accounting': KeyInfo(can_disable=True), + 'signal-range': KeyInfo(can_disable=True), + 'ssid-regexp': KeyInfo(), + 'time': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + 'vlan-mode': KeyInfo(can_disable=True), + }, + ), + ('caps-man', 'configuration'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'channel': KeyInfo(can_disable=True), + 'channel.band': KeyInfo(can_disable=True), + 'channel.control-channel-width': KeyInfo(can_disable=True), + 'channel.extension-channel': KeyInfo(can_disable=True), + 'channel.frequency': KeyInfo(can_disable=True), + 'channel.reselect-interval': KeyInfo(can_disable=True), + 'channel.save-selected': KeyInfo(can_disable=True), + 'channel.secondary-frequency': KeyInfo(can_disable=True), + 'channel.skip-dfs-channels': KeyInfo(can_disable=True), + 'channel.tx-power': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'country': KeyInfo(can_disable=True), + 'datapath': KeyInfo(can_disable=True), + 'datapath.arp': KeyInfo(), + 'datapath.bridge': KeyInfo(can_disable=True), + 'datapath.bridge-cost': KeyInfo(can_disable=True), + 'datapath.bridge-horizon': KeyInfo(can_disable=True), + 'datapath.client-to-client-forwarding': KeyInfo(can_disable=True), + 'datapath.interface-list': KeyInfo(can_disable=True), + 'datapath.l2mtu': KeyInfo(), + 'datapath.local-forwarding': KeyInfo(can_disable=True), + 'datapath.mtu': KeyInfo(), + 'datapath.openflow-switch': KeyInfo(can_disable=True), + 'datapath.vlan-id': KeyInfo(can_disable=True), + 'datapath.vlan-mode': KeyInfo(can_disable=True), + 'disconnect-timeout': KeyInfo(can_disable=True), + 'distance': KeyInfo(can_disable=True), + 'frame-lifetime': KeyInfo(can_disable=True), + 'guard-interval': KeyInfo(can_disable=True), + 'hide-ssid': KeyInfo(can_disable=True), + 'hw-protection-mode': KeyInfo(can_disable=True), + 'hw-retries': KeyInfo(can_disable=True), + 'installation': KeyInfo(can_disable=True), + 'keepalive-frames': KeyInfo(can_disable=True), + 'load-balancing-group': KeyInfo(can_disable=True), + 'max-sta-count': KeyInfo(can_disable=True), + 'mode': KeyInfo(can_disable=True), + 'multicast-helper': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'rates': KeyInfo(can_disable=True), + 'rates.basic': KeyInfo(can_disable=True), + 'rates.ht-basic-mcs': KeyInfo(can_disable=True), + 'rates.ht-supported-mcs': KeyInfo(can_disable=True), + 'rates.supported': KeyInfo(can_disable=True), + 'rates.vht-basic-mcs': KeyInfo(can_disable=True), + 'rates.vht-supported-mcs': KeyInfo(can_disable=True), + 'rx-chains': KeyInfo(can_disable=True), + 'security': KeyInfo(can_disable=True), + 'security.authentication-types': KeyInfo(can_disable=True), + 'security.disable-pmkid': KeyInfo(can_disable=True), + 'security.eap-methods': KeyInfo(can_disable=True), + 'security.eap-radius-accounting': KeyInfo(can_disable=True), + 'security.encryption': KeyInfo(can_disable=True), + 'security.group-encryption': KeyInfo(can_disable=True), + 'security.group-key-update': KeyInfo(), + 'security.passphrase': KeyInfo(can_disable=True), + 'security.tls-certificate': KeyInfo(), + 'security.tls-mode': KeyInfo(), + 'ssid': KeyInfo(can_disable=True), + 'tx-chains': KeyInfo(can_disable=True), + }, + ), + ('caps-man', 'datapath'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(), + 'bridge': KeyInfo(can_disable=True), + 'bridge-cost': KeyInfo(can_disable=True), + 'bridge-horizon': KeyInfo(can_disable=True), + 'client-to-client-forwarding': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'interface-list': KeyInfo(can_disable=True), + 'l2mtu': KeyInfo(), + 'local-forwarding': KeyInfo(can_disable=True), + 'mtu': KeyInfo(), + 'name': KeyInfo(), + 'openflow-switch': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + 'vlan-mode': KeyInfo(can_disable=True), + }, + ), ('caps-man', 'manager', 'interface'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -509,6 +617,41 @@ PATHS = { 'interface': KeyInfo(), }, ), + ('caps-man', 'provisioning'): APIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='none'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'common-name-regexp': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'hw-supported-modes': KeyInfo(default=''), + 'identity-regexp': KeyInfo(default=''), + 'ip-address-ranges': KeyInfo(default=''), + 'master-configuration': KeyInfo(default='*FFFFFFFF'), + 'name-format': KeyInfo(default='cap'), + 'name-prefix': KeyInfo(default=''), + 'radio-mac': KeyInfo(default='00:00:00:00:00:00'), + 'slave-configurations': KeyInfo(default=''), + }, + ), + ('caps-man', 'security'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'authentication-types': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disable-pmkid': KeyInfo(can_disable=True), + 'eap-methods': KeyInfo(can_disable=True), + 'eap-radius-accounting': KeyInfo(can_disable=True), + 'encryption': KeyInfo(can_disable=True), + 'group-encryption': KeyInfo(can_disable=True), + 'group-key-update': KeyInfo(), + 'name': KeyInfo(), + 'passphrase': KeyInfo(can_disable=True), + 'tls-certificate': KeyInfo(), + 'tls-mode': KeyInfo(), + } + ), ('certificate', 'settings'): APIData( single_value=True, fully_understood=True, @@ -1948,6 +2091,7 @@ PATHS = { ), ('caps-man', 'manager'): APIData( single_value=True, + fully_understood=True, fields={ 'ca-certificate': KeyInfo(default='none'), 'certificate': KeyInfo(default='none'), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5cc5075..5820c28 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -43,6 +43,12 @@ options: choices: # BEGIN PATH LIST - caps-man aaa + - caps-man access-list + - caps-man configuration + - caps-man datapath + - caps-man manager + - caps-man provisioning + - caps-man security - certificate settings - interface bridge - interface bridge port diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d83cc70..f8dfbdc 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -48,6 +48,12 @@ options: choices: # BEGIN PATH LIST - caps-man aaa + - caps-man access-list + - caps-man configuration + - caps-man datapath + - caps-man manager + - caps-man provisioning + - caps-man security - certificate settings - interface bridge - interface bridge port From 29247faaa31b61713ab818609442b9163d3b8a6f Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Sun, 13 Nov 2022 10:02:29 +0100 Subject: [PATCH 078/365] system logging API paths (#127) * api path support: system logging action Signed-off-by: Tomas Herfert * api path support: system logging Signed-off-by: Tomas Herfert * docs & changelog Signed-off-by: Tomas Herfert * typo fix Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert --- changelogs/fragments/127-logging.yml | 3 ++ plugins/module_utils/_api_data.py | 46 +++++++++++++++------------- plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 changelogs/fragments/127-logging.yml diff --git a/changelogs/fragments/127-logging.yml b/changelogs/fragments/127-logging.yml new file mode 100644 index 0000000..59245d2 --- /dev/null +++ b/changelogs/fragments/127-logging.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API paths ``system logging``, ``system logging action`` + (https://github.com/ansible-collections/community.routeros/pull/127). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 17acb29..5bac534 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2059,24 +2059,28 @@ PATHS = { }, ), ('system', 'logging', 'action'): APIData( - has_identifier=True, + fully_understood=True, + primary_keys=('name',), fields={ - 'bsd-syslog': KeyInfo(), - 'disk-file-count': KeyInfo(), - 'disk-file-name': KeyInfo(), - 'disk-lines-per-file': KeyInfo(), - 'disk-stop-on-full': KeyInfo(), - 'memory-lines': KeyInfo(), - 'memory-stop-on-full': KeyInfo(), + 'bsd-syslog': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disk-file-count': KeyInfo(default=2), + 'disk-file-name': KeyInfo(default='log'), + 'disk-lines-per-file': KeyInfo(default=1000), + 'disk-stop-on-full': KeyInfo(default=False), + 'email-start-tls': KeyInfo(default=False), + 'email-to': KeyInfo(default=''), + 'memory-lines': KeyInfo(default=1000), + 'memory-stop-on-full': KeyInfo(default=False), 'name': KeyInfo(), - 'remember': KeyInfo(), - 'remote': KeyInfo(), - 'remote-port': KeyInfo(), - 'src-address': KeyInfo(), - 'syslog-facility': KeyInfo(), - 'syslog-severity': KeyInfo(), - 'syslog-time-format': KeyInfo(), - 'target': KeyInfo(), + 'remember': KeyInfo(default=True), + 'remote': KeyInfo(default='0.0.0.0'), + 'remote-port': KeyInfo(default=514), + 'src-address': KeyInfo(default='0.0.0.0'), + 'syslog-facility': KeyInfo(default='daemon'), + 'syslog-severity': KeyInfo(default='auto'), + 'syslog-time-format': KeyInfo(default='bsd-syslog'), + 'target': KeyInfo(required=True), }, ), ('user', 'group'): APIData( @@ -2148,12 +2152,12 @@ PATHS = { }, ), ('system', 'logging'): APIData( - has_identifier=True, + fully_understood=True, fields={ - 'action': KeyInfo(), - 'disabled': KeyInfo(), - 'prefix': KeyInfo(), - 'topics': KeyInfo(), + 'action': KeyInfo(default='memory'), + 'disabled': KeyInfo(default=False), + 'prefix': KeyInfo(default=''), + 'topics': KeyInfo(default=''), }, ), ('system', 'resource', 'irq'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5820c28..b8d6aa6 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -127,6 +127,8 @@ options: - system clock manual - system identity - system leds settings + - system logging + - system logging action - system note - system ntp client - system ntp client servers diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index f8dfbdc..633836b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -132,6 +132,8 @@ options: - system clock manual - system identity - system leds settings + - system logging + - system logging action - system note - system ntp client - system ntp client servers From c48f4c74ce3792755b5d1b5adeba666a2c35d0be Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Sun, 13 Nov 2022 21:14:45 +0100 Subject: [PATCH 079/365] support for multiple "ip ipsec *" API paths (#129) Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert --- changelogs/fragments/129-api-ipsec.yml | 3 + plugins/module_utils/_api_data.py | 101 +++++++++++++++++++------ plugins/modules/api_info.py | 5 ++ plugins/modules/api_modify.py | 5 ++ 4 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 changelogs/fragments/129-api-ipsec.yml diff --git a/changelogs/fragments/129-api-ipsec.yml b/changelogs/fragments/129-api-ipsec.yml new file mode 100644 index 0000000..c13b7a7 --- /dev/null +++ b/changelogs/fragments/129-api-ipsec.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` + (https://github.com/ansible-collections/community.routeros/pull/129). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5bac534..ad8ceb2 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -301,6 +301,31 @@ PATHS = { 'transparent-proxy': KeyInfo(), }, ), + ('ip', 'ipsec', 'identity'): APIData( + fully_understood=True, + primary_keys=('peer', ), + fields={ + 'auth-method': KeyInfo(default='pre-shared-key'), + 'certificate': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'eap-methods': KeyInfo(default='eap-tls'), + 'generate-policy': KeyInfo(default=False), + 'key': KeyInfo(), + 'match-by': KeyInfo(can_disable=True, remove_value='remote-id'), + 'mode-config': KeyInfo(can_disable=True, remove_value='none'), + 'my-id': KeyInfo(can_disable=True, remove_value='auto'), + 'notrack-chain': KeyInfo(can_disable=True, remove_value=''), + 'password': KeyInfo(), + 'peer': KeyInfo(), + 'policy-template-group': KeyInfo(can_disable=True, remove_value='default'), + 'remote-certificate': KeyInfo(), + 'remote-id': KeyInfo(can_disable=True, remove_value='auto'), + 'remote-key': KeyInfo(), + 'secret': KeyInfo(default=''), + 'username': KeyInfo(), + }, + ), ('ip', 'ipsec', 'mode-config'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -311,6 +336,22 @@ PATHS = { 'use-responder-dns': KeyInfo(), }, ), + ('ip', 'ipsec', 'peer'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'exchange-mode': KeyInfo(default='main'), + 'local-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'name': KeyInfo(), + 'passive': KeyInfo(can_disable=True, remove_value=False), + 'port': KeyInfo(can_disable=True, remove_value=500), + 'profile': KeyInfo(default='default'), + 'send-initial-contact': KeyInfo(default=True), + }, + ), ('ip', 'ipsec', 'policy', 'group'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -320,32 +361,32 @@ PATHS = { }, ), ('ip', 'ipsec', 'profile'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'dh-group': KeyInfo(), - 'dpd-interval': KeyInfo(), - 'dpd-maximum-failures': KeyInfo(), - 'enc-algorithm': KeyInfo(), - 'hash-algorithm': KeyInfo(), - 'lifetime': KeyInfo(), + 'dh-group': KeyInfo(default='modp2048,modp1024'), + 'dpd-interval': KeyInfo(default='2m'), + 'dpd-maximum-failures': KeyInfo(default=5), + 'enc-algorithm': KeyInfo(default='aes-128,3des'), + 'hash-algorithm': KeyInfo(default='sha1'), + 'lifebytes': KeyInfo(can_disable=True, remove_value=0), + 'lifetime': KeyInfo(default='1d'), 'name': KeyInfo(), - 'nat-traversal': KeyInfo(), - 'proposal-check': KeyInfo(), + 'nat-traversal': KeyInfo(default=True), + 'prf-algorithm': KeyInfo(can_disable=True, remove_value='auto'), + 'proposal-check': KeyInfo(default='obey'), }, ), ('ip', 'ipsec', 'proposal'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'auth-algorithms': KeyInfo(), - 'disabled': KeyInfo(), - 'enc-algorithms': KeyInfo(), - 'lifetime': KeyInfo(), + 'auth-algorithms': KeyInfo(default='sha1'), + 'disabled': KeyInfo(default=False), + 'enc-algorithms': KeyInfo(default='aes-256-cbc,aes-192-cbc,aes-128-cbc'), + 'lifetime': KeyInfo(default='30m'), 'name': KeyInfo(), - 'pfs-group': KeyInfo(), + 'pfs-group': KeyInfo(default='modp1024'), }, ), ('ip', 'pool'): APIData( @@ -2127,15 +2168,25 @@ PATHS = { }, ), ('ip', 'ipsec', 'policy'): APIData( - has_identifier=True, + fully_understood=True, fields={ - 'disabled': KeyInfo(), + 'action': KeyInfo(default='encrypt'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), 'dst-address': KeyInfo(), - 'group': KeyInfo(), - 'proposal': KeyInfo(), - 'protocol': KeyInfo(), + 'dst-port': KeyInfo(default='any'), + 'group': KeyInfo(can_disable=True, remove_value='default'), + 'ipsec-protocols': KeyInfo(default='esp'), + 'level': KeyInfo(default='require'), + 'peer': KeyInfo(), + 'proposal': KeyInfo(default='default'), + 'protocol': KeyInfo(default='all'), 'src-address': KeyInfo(), - 'template': KeyInfo(), + 'src-port': KeyInfo(default='any'), + 'template': KeyInfo(can_disable=True, remove_value=False), + # the tepmlate field can't really be changed once the item is created. This config captures the behavior best as it can + # i.e. tepmplate=yes is shown, tepmlate=no is hidden + 'tunnel': KeyInfo(default=False), }, ), ('ip', 'service'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index b8d6aa6..92ca1a2 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -92,6 +92,11 @@ options: - ip firewall nat - ip firewall service-port - ip hotspot service-port + - ip ipsec identity + - ip ipsec peer + - ip ipsec policy + - ip ipsec profile + - ip ipsec proposal - ip ipsec settings - ip neighbor discovery-settings - ip pool diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 633836b..4f3dbe8 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -97,6 +97,11 @@ options: - ip firewall nat - ip firewall service-port - ip hotspot service-port + - ip ipsec identity + - ip ipsec peer + - ip ipsec policy + - ip ipsec profile + - ip ipsec proposal - ip ipsec settings - ip neighbor discovery-settings - ip pool From 4194ae9ba6e9041162249f42ea83bd2b7c699030 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Tue, 15 Nov 2022 22:11:55 +0100 Subject: [PATCH 080/365] multiple api paths support and updates (#131) * multiple api paths support and updates Signed-off-by: Tomas Herfert * sanity fix Signed-off-by: Tomas Herfert * another sanity fix Signed-off-by: Tomas Herfert * Apply suggestions from code review Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/131-api.yml | 15 +++ plugins/module_utils/_api_data.py | 208 +++++++++++++++++++++++++----- plugins/modules/api_info.py | 11 ++ plugins/modules/api_modify.py | 11 ++ 4 files changed, 212 insertions(+), 33 deletions(-) create mode 100644 changelogs/fragments/131-api.yml diff --git a/changelogs/fragments/131-api.yml b/changelogs/fragments/131-api.yml new file mode 100644 index 0000000..8e2ad1c --- /dev/null +++ b/changelogs/fragments/131-api.yml @@ -0,0 +1,15 @@ +minor_changes: + - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` + (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path + (https://github.com/ansible-collections/community.routeros/pull/131). +known_issues: + - api_modify - when limits for entries in ``queue tree`` are defined as human readable - for example ``25M`` -, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - for example ``25000000`` (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI) + (https://github.com/ansible-collections/community.routeros/pull/131). + - "api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 + (https://github.com/ansible-collections/community.routeros/pull/131)." +bugfixes: + - "api_modify - ``queue interface`` path works now + (https://github.com/ansible-collections/community.routeros/pull/131)." + - "api_modify - ``ip route`` entry can be defined without the need of ``gateway`` field, which is correct for unreachable/blackhole type of routes + (https://github.com/ansible-collections/community.routeros/pull/131)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ad8ceb2..fa4765d 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -400,16 +400,22 @@ PATHS = { ('ip', 'route'): APIData( fully_understood=True, fields={ + 'blackhole': KeyInfo(can_disable=True), 'check-gateway': KeyInfo(can_disable=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'distance': KeyInfo(), 'dst-address': KeyInfo(), - 'gateway': KeyInfo(required=True), + 'gateway': KeyInfo(), + 'pref-src': KeyInfo(), + 'routing-table': KeyInfo(default='main'), 'route-tag': KeyInfo(can_disable=True), 'routing-mark': KeyInfo(can_disable=True), 'scope': KeyInfo(), + 'suppress-hw-offload': KeyInfo(default=False), 'target-scope': KeyInfo(), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'vrf-interface': KeyInfo(can_disable=True), }, ), ('ip', 'route', 'vrf'): APIData( @@ -437,45 +443,78 @@ PATHS = { }, ), ('routing', 'ospf', 'instance'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'distribute-default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), 'domain-id': KeyInfo(can_disable=True), 'domain-tag': KeyInfo(can_disable=True), - 'in-filter': KeyInfo(), - 'metric-bgp': KeyInfo(), - 'metric-connected': KeyInfo(), - 'metric-default': KeyInfo(), - 'metric-other-ospf': KeyInfo(), - 'metric-rip': KeyInfo(), - 'metric-static': KeyInfo(), + 'in-filter-chain': KeyInfo(can_disable=True), + 'mpls-te-address': KeyInfo(can_disable=True), 'mpls-te-area': KeyInfo(can_disable=True), - 'mpls-te-router-id': KeyInfo(can_disable=True), 'name': KeyInfo(), - 'out-filter': KeyInfo(), - 'redistribute-bgp': KeyInfo(), - 'redistribute-connected': KeyInfo(), - 'redistribute-other-ospf': KeyInfo(), - 'redistribute-rip': KeyInfo(), - 'redistribute-static': KeyInfo(), - 'router-id': KeyInfo(), + 'originate-default': KeyInfo(can_disable=True), + 'out-filter-chain': KeyInfo(can_disable=True), + 'out-filter-select': KeyInfo(can_disable=True), + 'redistribute': KeyInfo(can_disable=True), + 'router-id': KeyInfo(default='main'), 'routing-table': KeyInfo(can_disable=True), 'use-dn': KeyInfo(can_disable=True), + 'version': KeyInfo(default=2), + 'vrf': KeyInfo(default='main'), }, ), ('routing', 'ospf', 'area'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'area-id': KeyInfo(), - 'disabled': KeyInfo(), - 'instance': KeyInfo(), + 'area-id': KeyInfo(default='0.0.0.0'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'instance': KeyInfo(required=True), 'name': KeyInfo(), - 'type': KeyInfo(), + 'no-summaries': KeyInfo(can_disable=True), + 'nssa-translator': KeyInfo(can_disable=True), + 'type': KeyInfo(default='default'), + }, + ), + ('routing', 'ospf', 'area', 'range'): APIData( + fully_understood=True, + primary_keys=('area', 'prefix', ), + fields={ + 'advertise': KeyInfo(default=True), + 'area': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'prefix': KeyInfo(), + }, + ), + ('routing', 'ospf', 'interface-template'): APIData( + fully_understood=True, + fields={ + 'area': KeyInfo(required=True), + 'auth': KeyInfo(can_disable=True), + 'auth-id': KeyInfo(can_disable=True), + 'auth-key': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(default=1), + 'dead-interval': KeyInfo(default='40s'), + 'disabled': KeyInfo(default=False), + 'hello-interval': KeyInfo(default='10s'), + 'instance-id': KeyInfo(default=0), + 'interfaces': KeyInfo(can_disable=True), + 'networks': KeyInfo(can_disable=True), + 'passive': KeyInfo(can_disable=True), + 'prefix-list': KeyInfo(can_disable=True), + 'priority': KeyInfo(default=128), + 'retransmit-interval': KeyInfo(default='5s'), + 'transmit-delay': KeyInfo(default='1s'), + 'type': KeyInfo(default='broadcast'), + 'vlink-neighbor-id': KeyInfo(can_disable=True), + 'vlink-transit-area': KeyInfo(can_disable=True), }, ), ('routing', 'ospf-v3', 'instance'): APIData( @@ -512,6 +551,40 @@ PATHS = { 'type': KeyInfo(), }, ), + ('routing', 'pimsm', 'instance'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'afi': KeyInfo(default='ipv4'), + 'bsm-forward-back': KeyInfo(), + 'crp-advertise-contained': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'rp-hash-mask-length': KeyInfo(), + 'rp-static-override': KeyInfo(default=False), + 'ssm-range': KeyInfo(), + 'switch-to-spt': KeyInfo(default=True), + 'switch-to-spt-bytes': KeyInfo(default=0), + 'switch-to-spt-interval': KeyInfo(), + 'vrf': KeyInfo(default="main"), + }, + ), + ('routing', 'pimsm', 'interface-template'): APIData( + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'hello-delay': KeyInfo(default='5s'), + 'hello-period': KeyInfo(default='30s'), + 'instance': KeyInfo(required=True), + 'interfaces': KeyInfo(can_disable=True), + 'join-prune-period': KeyInfo(default='1m'), + 'join-tracking-support': KeyInfo(default=True), + 'override-interval': KeyInfo(default='2s500ms'), + 'priority': KeyInfo(default=1), + 'propagation-delay': KeyInfo(default='500ms'), + 'source-addresses': KeyInfo(can_disable=True), + }, + ), ('snmp', 'community'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -824,6 +897,19 @@ PATHS = { 'tcp-syncookies': KeyInfo(default=False), }, ), + ('ipv6', 'address'): APIData( + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'advertise': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'eui-64': KeyInfo(default=False), + 'from-pool': KeyInfo(), + 'interface': KeyInfo(required=True), + 'no-dad': KeyInfo(default=False), + }, + ), ('ipv6', 'settings'): APIData( single_value=True, fully_understood=True, @@ -1467,6 +1553,36 @@ PATHS = { 'use-peer-dns': KeyInfo(default=True), }, ), + ('ipv6', 'dhcp-server'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(required=True), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'binding-script': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), + 'interface': KeyInfo(required=True), + 'lease-time': KeyInfo(default='3d'), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'preference': KeyInfo(default=255), + 'rapid-commit': KeyInfo(default=True), + 'route-distance': KeyInfo(default=1), + 'use-radius': KeyInfo(default=False), + }, + ), + ('ipv6', 'dhcp-server', 'option'): APIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'code': KeyInfo(required=True), + 'name': KeyInfo(), + 'value': KeyInfo(default=''), + }, + ), ('ipv6', 'firewall', 'address-list'): APIData( fully_understood=True, primary_keys=('address', 'list', ), @@ -1562,6 +1678,7 @@ PATHS = { }, ), ('ipv6', 'route'): APIData( + fully_understood=True, fields={ 'bgp-as-path': KeyInfo(can_disable=True), 'bgp-atomic-aggregate': KeyInfo(can_disable=True), @@ -1570,14 +1687,19 @@ PATHS = { 'bgp-med': KeyInfo(can_disable=True), 'bgp-origin': KeyInfo(can_disable=True), 'bgp-prepend': KeyInfo(can_disable=True), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'blackhole': KeyInfo(can_disable=True), 'check-gateway': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(), - 'distance': KeyInfo(), + 'distance': KeyInfo(default=1), 'dst-address': KeyInfo(), 'gateway': KeyInfo(), 'route-tag': KeyInfo(can_disable=True), - 'scope': KeyInfo(), - 'target-scope': KeyInfo(), + 'routing-table': KeyInfo(default='main'), + 'scope': KeyInfo(default=30), + 'target-scope': KeyInfo(default=10), + 'vrf-interface': KeyInfo(can_disable=True), }, ), ('mpls', ): APIData( @@ -1977,11 +2099,31 @@ PATHS = { }, ), ('queue', 'interface'): APIData( + primary_keys=('interface', ), + fully_understood=True, + fixed_entries=True, + fields={ + 'interface': KeyInfo(required=True), + 'queue': KeyInfo(required=True), + }, + ), + ('queue', 'tree'): APIData( primary_keys=('name', ), fully_understood=True, fields={ - 'name': KeyInfo(required=True), - 'queue': KeyInfo(required=True), + 'bucket-size': KeyInfo(default='0.1'), + 'burst-limit': KeyInfo(default=0), + 'burst-threshold': KeyInfo(default=0), + 'burst-time': KeyInfo(default='0s'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'limit-at': KeyInfo(default=0), + 'max-limit': KeyInfo(default=0), + 'name': KeyInfo(), + 'packet-mark': KeyInfo(default=''), + 'parent': KeyInfo(required=True), + 'priority': KeyInfo(default=8), + 'queue': KeyInfo(default='default-small'), }, ), ('interface', 'ethernet', 'switch'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 92ca1a2..337f11c 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -112,19 +112,30 @@ options: - ip traffic-flow - ip traffic-flow ipfix - ip upnp + - ipv6 address - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter - ipv6 nd prefix default + - ipv6 route - ipv6 settings - mpls - mpls ldp - port firmware - ppp aaa - queue interface + - queue tree - radius incoming - routing bgp instance - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing pimsm instance + - routing pimsm interface-template - routing rip - routing ripng - snmp diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 4f3dbe8..97f832d 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -117,19 +117,30 @@ options: - ip traffic-flow - ip traffic-flow ipfix - ip upnp + - ipv6 address - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter - ipv6 nd prefix default + - ipv6 route - ipv6 settings - mpls - mpls ldp - port firmware - ppp aaa - queue interface + - queue tree - radius incoming - routing bgp instance - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing pimsm instance + - routing pimsm interface-template - routing rip - routing ripng - snmp From b539ed6aa48706921526744b1b0cd8603e6ca378 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Wed, 16 Nov 2022 22:31:49 +0100 Subject: [PATCH 081/365] make api_modify to ignore builtin items (#130) * make api_modify to ignore builtin items Signed-off-by: Tomas Herfert * include_builtin parametr for api_info module Signed-off-by: Tomas Herfert * api_info ignore_builtin changelog Signed-off-by: Tomas Herfert * typo Signed-off-by: Tomas Herfert * Apply suggestions from code review Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- .../fragments/130-api-modify-builtin.yml | 6 ++++++ plugins/modules/api_info.py | 21 ++++++++++++++++--- plugins/modules/api_modify.py | 4 ++-- 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/130-api-modify-builtin.yml diff --git a/changelogs/fragments/130-api-modify-builtin.yml b/changelogs/fragments/130-api-modify-builtin.yml new file mode 100644 index 0000000..01d8b55 --- /dev/null +++ b/changelogs/fragments/130-api-modify-builtin.yml @@ -0,0 +1,6 @@ +minor_changes: + - api_info - new parameter ``include_builtin`` which allows to include "builtin" entries that are automatically generated by ROS and cannot be modified by the user + (https://github.com/ansible-collections/community.routeros/pull/130). +trivial: + - api_modify - ignore ``builtin`` entries + (https://github.com/ansible-collections/community.routeros/pull/130). diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 337f11c..03d024e 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -18,9 +18,9 @@ version_added: 2.2.0 description: - Allows to retrieve information for a path using the API. - This can be used to backup a path to restore it with the M(community.routeros.api_modify) module. - - Entries are normalized, and dynamic entries are not returned. Use the I(handle_disabled) and - I(hide_defaults) options to control normalization, the I(include_dynamic) option to also return - dynamic entries, and use I(unfiltered) to return all fields including counters. + - Entries are normalized, dynamic and builtin entries are not returned. Use the I(handle_disabled) and + I(hide_defaults) options to control normalization, the I(include_dynamic) and I(include_builtin) options to also return + dynamic resp. builtin entries, and use I(unfiltered) to return all fields including counters. - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). @@ -196,6 +196,14 @@ options: - If set to C(true), they are returned as well, and the C(dynamic) keys are returned as well. type: bool default: false + include_builtin: + description: + - Whether to include builtin values. + - By default, they are not returned, and the C(builtin) keys are omitted. + - If set to C(true), they are returned as well, and the C(builtin) keys are returned as well. + type: bool + default: false + version_added: 2.4.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -273,6 +281,7 @@ def main(): handle_disabled=dict(type='str', choices=['exclamation', 'null-value', 'omit'], default='exclamation'), hide_defaults=dict(type='bool', default=True), include_dynamic=dict(type='bool', default=False), + include_builtin=dict(type='bool', default=False), ) module_args.update(api_argument_spec()) @@ -292,6 +301,7 @@ def main(): handle_disabled = module.params['handle_disabled'] hide_defaults = module.params['hide_defaults'] include_dynamic = module.params['include_dynamic'] + include_builtin = module.params['include_builtin'] try: api_path = compose_api_path(api, path) @@ -301,12 +311,17 @@ def main(): if not include_dynamic: if entry.get('dynamic', False): continue + if not include_builtin: + if entry.get('builtin', False): + continue if not unfiltered: for k in list(entry): if k == '.id': continue if k == 'dynamic' and include_dynamic: continue + if k == 'builtin' and include_builtin: + continue if k not in path_info.fields: entry.pop(k) if handle_disabled != 'omit': diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 97f832d..0306db3 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -20,7 +20,7 @@ description: - Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way depending on some search conditions. - To make a backup of a path that can be restored with this module, use the M(community.routeros.api_info) module. - - The module ignores dynamic entries. + - The module ignores dynamic and builtin entries. - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). @@ -483,7 +483,7 @@ def match_entries(new_entries, old_entries, path_info, module): def remove_dynamic(entries): result = [] for entry in entries: - if entry.get('dynamic', False): + if entry.get('dynamic', False) or entry.get('builtin', False): continue result.append(entry) return result From 1353055fe26ea90b43dc85741646e3847fe361ee Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 17 Nov 2022 12:42:01 +0100 Subject: [PATCH 082/365] Allow changelog fragments with .yaml ending. --- tests/sanity/extra/licenses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py index 127288c..80eb795 100755 --- a/tests/sanity/extra/licenses.py +++ b/tests/sanity/extra/licenses.py @@ -67,6 +67,7 @@ def main(): # The following paths are allowed to have no license identifier no_comments_allowed = [ 'changelogs/fragments/*.yml', + 'changelogs/fragments/*.yaml', ] # These files are completely ignored From 23b3aa3beb134caf64a402c6c20c354448605f5a Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:48:50 +0100 Subject: [PATCH 083/365] API update (#128) * adding support for api fields that can be disabled and have default value at the same time Signed-off-by: Tomas Herfert * api path support: interface gre Signed-off-by: Tomas Herfert * docs Signed-off-by: Tomas Herfert * unit test update & yamlling fix Signed-off-by: Tomas Herfert * test fix Signed-off-by: Tomas Herfert * sanity fix Signed-off-by: Tomas Herfert * changelog Signed-off-by: Tomas Herfert * Update per suggestion Co-authored-by: Felix Fontein * api path support: interface eoip Signed-off-by: Tomas Herfert * docs Signed-off-by: Tomas Herfert * apply suggestion from code review Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/128-api.yml | 3 ++ plugins/module_utils/_api_data.py | 49 ++++++++++++++++++- plugins/modules/api_info.py | 2 + plugins/modules/api_modify.py | 13 ++++- .../plugins/module_utils/test__api_data.py | 10 +++- tests/unit/plugins/modules/fake_api.py | 2 +- 6 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/128-api.yml diff --git a/changelogs/fragments/128-api.yml b/changelogs/fragments/128-api.yml new file mode 100644 index 0000000..6bcc4b7 --- /dev/null +++ b/changelogs/fragments/128-api.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support for API fields that can be disabled and have default value at the same time, support API paths ``interface gre``, ``interface eoip`` + (https://github.com/ansible-collections/community.routeros/pull/128). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fa4765d..c094821 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -49,8 +49,10 @@ class KeyInfo(object): def __init__(self, _dummy=None, can_disable=False, remove_value=None, absent_value=None, default=None, required=False, automatically_computed_from=None): if _dummy is not None: raise ValueError('KeyInfo() does not have positional arguments') - if sum([required, default is not None, automatically_computed_from is not None, can_disable]) > 1: - raise ValueError('required, default, automatically_computed_from, and can_disable are mutually exclusive') + if sum([required, default is not None or can_disable, automatically_computed_from is not None]) > 1: + raise ValueError( + 'required, default, automatically_computed_from, and can_disable are mutually exclusive ' + + 'besides default and can_disable which can be set together') if not can_disable and remove_value is not None: raise ValueError('remove_value can only be specified if can_disable=True') if absent_value is not None and any([default is not None, automatically_computed_from is not None, can_disable]): @@ -106,6 +108,31 @@ PATHS = { 'vlan-filtering': KeyInfo(default=False), }, ), + ('interface', 'eoip'): APIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dont-fragment': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='0.0.0.0'), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mac-address': KeyInfo(), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + 'tunnel-id': KeyInfo(required=True), + }, + ), ('interface', 'ethernet'): APIData( fixed_entries=True, fully_understood=True, @@ -145,6 +172,24 @@ PATHS = { 'tx-flow-control': KeyInfo(default='off'), }, ), + ('interface', 'gre'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dont-fragment': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='0.0.0.0'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + }, + ), ('interface', 'list'): APIData( primary_keys=('name', ), fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 03d024e..f8e9337 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -57,9 +57,11 @@ options: - interface bridge settings - interface bridge vlan - interface detect-internet + - interface eoip - interface ethernet - interface ethernet switch - interface ethernet switch port + - interface gre - interface l2tp-server server - interface list - interface list member diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 0306db3..fc57ee0 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -62,9 +62,11 @@ options: - interface bridge settings - interface bridge vlan - interface detect-internet + - interface eoip - interface ethernet - interface ethernet switch - interface ethernet switch port + - interface gre - interface l2tp-server server - interface list - interface list member @@ -352,7 +354,7 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret modifications['!%s' % disabled_k] = '' del updated_entry[disabled_k] continue - if k not in old_entry and path_info.fields[k].default == v: + if k not in old_entry and path_info.fields[k].default == v and not path_info.fields[k].can_disable: continue if k not in old_entry or old_entry[k] != v: modifications[k] = v @@ -368,7 +370,9 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret if field_info.remove_value is not None and field_info.remove_value == old_entry[k]: continue if field_info.can_disable: - if field_info.remove_value is not None: + if field_info.default is not None: + modifications[k] = field_info.default + elif field_info.remove_value is not None: modifications[k] = field_info.remove_value else: modifications['!%s' % k] = '' @@ -380,6 +384,11 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret if return_none_instead_of_fail: return None, None module.fail_json(msg='Key "{key}" cannot be removed{for_text}.'.format(key=k, for_text=for_text)) + for k in path_info.fields: + field_info = path_info.fields[k] + if k not in old_entry and k not in new_entry and field_info.can_disable and field_info.default is not None: + modifications[k] = field_info.default + updated_entry[k] = field_info.default return modifications, updated_entry diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 67b5b1b..6220e29 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -63,11 +63,19 @@ def test_key_info_errors(): ('can_disable', True), ] + params_allowed_together = [ + 'default', + 'can_disable', + ] + + emsg = 'required, default, automatically_computed_from, and can_disable are mutually exclusive besides default and can_disable which can be set together' for index, (param, param_value) in enumerate(values): for param2, param2_value in values[index + 1:]: + if param in params_allowed_together and param2 in params_allowed_together: + continue with pytest.raises(ValueError) as exc: KeyInfo(**{param: param_value, param2: param2_value}) - assert exc.value.args[0] == 'required, default, automatically_computed_from, and can_disable are mutually exclusive' + assert exc.value.args[0] == emsg with pytest.raises(ValueError) as exc: KeyInfo('foo') diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index b17c088..f50c996 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -120,7 +120,7 @@ class Or(object): def _normalize_entry(entry, path_info): for key, data in path_info.fields.items(): - if key not in entry and data.default is not None: + if key not in entry and data.default is not None and not data.can_disable: entry[key] = data.default if data.can_disable: if key in entry and entry[key] in (None, data.remove_value): From 5af14a894012148b6a1cdc76b3ced38a0499fc96 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Thu, 17 Nov 2022 20:14:07 +0100 Subject: [PATCH 084/365] support for new API paths and few updates (#133) * support for new API paths and few updates Signed-off-by: Tomas Herfert * changelog fix Signed-off-by: Tomas Herfert * tests update Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert --- changelogs/fragments/133-api.yml | 11 + plugins/module_utils/_api_data.py | 234 ++++++++++++++++++-- plugins/modules/api_info.py | 7 + plugins/modules/api_modify.py | 7 + tests/unit/plugins/modules/test_api_info.py | 4 + 5 files changed, 247 insertions(+), 16 deletions(-) create mode 100644 changelogs/fragments/133-api.yml diff --git a/changelogs/fragments/133-api.yml b/changelogs/fragments/133-api.yml new file mode 100644 index 0000000..ecd8a62 --- /dev/null +++ b/changelogs/fragments/133-api.yml @@ -0,0 +1,11 @@ +minor_changes: + - api_modify, api_info - support API paths - ``interface bonding``, ``interface bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, ``system script``, ``system ups`` + (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support fields ``jump-target``, ``reject-with`` in ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` API path, field ``jump-target`` in ``ip firewall mangle`` API path, field ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, ``reject-with`` in ``ipv6 firewall filter`` API path + (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, ``packet-mark``, ``packet-size``, ``per-connection-classifier``, ``port``, ``priority``, ``psd``, ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, ``src-address``, ``src-address-list``, ``src-address-type``, ``src-mac-address``, ``src-port``, ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall nat`` path + (https://github.com/ansible-collections/community.routeros/pull/133). + +bugfixes: + - api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 firewall address-list`` + (https://github.com/ansible-collections/community.routeros/pull/133). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index c094821..133048c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -80,6 +80,33 @@ def join_path(path): # 3. All bold attributes go into the `primary_keys` list -- this is not always true! PATHS = { + ('interface', 'bonding'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-interval': KeyInfo(default='100ms'), + 'arp-ip-targets': KeyInfo(default=''), + 'arp-timeout': KeyInfo(default='auto'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'down-delay': KeyInfo(default='0ms'), + 'forced-mac-address': KeyInfo(can_disable=True), + 'lacp-rate': KeyInfo(default='30secs'), + 'lacp-user-key': KeyInfo(can_disable=True, remove_value=0), + 'link-monitoring': KeyInfo(default='mii'), + 'mii-interval': KeyInfo(default='100ms'), + 'min-links': KeyInfo(default=0), + 'mlag-id': KeyInfo(can_disable=True, remove_value=0), + 'mode': KeyInfo(default='balance-rr'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'primary': KeyInfo(default='none'), + 'slaves': KeyInfo(required=True), + 'transmit-hash-policy': KeyInfo(default='layer-2'), + 'up-delay': KeyInfo(default='0ms'), + } + ), ('interface', 'bridge'): APIData( fully_understood=True, primary_keys=('name', ), @@ -852,6 +879,14 @@ PATHS = { 'unknown-unicast-flood': KeyInfo(default=True), }, ), + ('interface', 'bridge', 'mlag'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'peer-port': KeyInfo(default='none'), + } + ), ('interface', 'bridge', 'port-controller'): APIData( single_value=True, fully_understood=True, @@ -1247,6 +1282,7 @@ PATHS = { primary_keys=('address', 'list', ), fields={ 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'list': KeyInfo(), }, @@ -1284,6 +1320,7 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), 'log': KeyInfo(), @@ -1302,6 +1339,7 @@ PATHS = { 'protocol': KeyInfo(can_disable=True), 'psd': KeyInfo(can_disable=True), 'random': KeyInfo(can_disable=True), + 'reject-with': KeyInfo(), 'routing-mark': KeyInfo(can_disable=True), 'routing-table': KeyInfo(can_disable=True), 'src-address': KeyInfo(can_disable=True), @@ -1348,6 +1386,7 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), 'log': KeyInfo(), @@ -1397,17 +1436,65 @@ PATHS = { stratify_keys=('chain', ), fields={ 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), 'in-interface': KeyInfo(can_disable=True), 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), 'out-interface': KeyInfo(can_disable=True), 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'realm': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'same-not-by-dst': KeyInfo(), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), 'to-addresses': KeyInfo(can_disable=True), 'to-ports': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), }, ), ('ip', 'hotspot', 'user'): APIData( @@ -1633,8 +1720,8 @@ PATHS = { primary_keys=('address', 'list', ), fields={ 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), - 'dynamic': KeyInfo(default=False), 'list': KeyInfo(), }, ), @@ -1668,6 +1755,7 @@ PATHS = { 'in-interface-list': KeyInfo(can_disable=True), 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), 'limit': KeyInfo(can_disable=True), 'log': KeyInfo(), 'log-prefix': KeyInfo(), @@ -1683,6 +1771,7 @@ PATHS = { 'priority': KeyInfo(can_disable=True), 'protocol': KeyInfo(can_disable=True), 'random': KeyInfo(can_disable=True), + 'reject-with': KeyInfo(), 'src-address': KeyInfo(can_disable=True), 'src-address-list': KeyInfo(can_disable=True), 'src-address-type': KeyInfo(can_disable=True), @@ -1693,24 +1782,97 @@ PATHS = { 'time': KeyInfo(can_disable=True), }, ), - ('ipv6', 'nd'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + ('ipv6', 'firewall', 'mangle'): APIData( + fully_understood=True, + stratify_keys=('chain', ), fields={ - 'default': KeyInfo(), - 'advertise-dns': KeyInfo(), - 'advertise-mac-address': KeyInfo(), + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), 'disabled': KeyInfo(), - 'hop-limit': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'dst-prefix': KeyInfo(), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'new-connection-mark': KeyInfo(), + 'new-dscp': KeyInfo(), + 'new-hop-limit': KeyInfo(), + 'new-mss': KeyInfo(), + 'new-packet-mark': KeyInfo(), + 'new-routing-mark': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'passthrough': KeyInfo(), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'sniff-id': KeyInfo(), + 'sniff-target': KeyInfo(), + 'sniff-target-port': KeyInfo(), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'src-prefix': KeyInfo(), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + } + ), + ('ipv6', 'nd'): APIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'advertise-dns': KeyInfo(default=True), + 'advertise-mac-address': KeyInfo(default=True), + 'disabled': KeyInfo(default=False), + 'dns': KeyInfo(default=''), + 'hop-limit': KeyInfo(default='unspecified'), 'interface': KeyInfo(), - 'managed-address-configuration': KeyInfo(), - 'mtu': KeyInfo(), - 'other-configuration': KeyInfo(), - 'ra-delay': KeyInfo(), - 'ra-interval': KeyInfo(), - 'ra-lifetime': KeyInfo(), - 'reachable-time': KeyInfo(), - 'retransmit-interval': KeyInfo(), + 'managed-address-configuration': KeyInfo(default=False), + 'mtu': KeyInfo(default='unspecified'), + 'other-configuration': KeyInfo(default=False), + 'ra-delay': KeyInfo(default='3s'), + 'ra-interval': KeyInfo(default='3m20s-10m'), + 'ra-lifetime': KeyInfo(default='30m'), + 'ra-preference': KeyInfo(default='medium'), + 'reachable-time': KeyInfo(default='unspecified'), + 'retransmit-interval': KeyInfo(default='unspecified'), }, ), ('ipv6', 'nd', 'prefix', 'default'): APIData( @@ -2003,6 +2165,20 @@ PATHS = { 'user': KeyInfo(default=''), }, ), + ('system', 'ups'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'alarm-setting': KeyInfo(default='immediate'), + 'check-capabilities': KeyInfo(can_disable=True, remove_value=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=True), + 'min-runtime': KeyInfo(default='never'), + 'name': KeyInfo(), + 'offline-time': KeyInfo(default='0s'), + 'port': KeyInfo(required=True), + }, + ), ('system', 'watchdog'): APIData( single_value=True, fully_understood=True, @@ -2404,4 +2580,30 @@ PATHS = { 'cpu': KeyInfo(), }, ), + ('system', 'scheduler'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interval': KeyInfo(default='0s'), + 'name': KeyInfo(), + 'on-event': KeyInfo(default=''), + 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), + 'start-date': KeyInfo(), + 'start-time': KeyInfo(), + }, + ), + ('system', 'script'): APIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dont-require-permissions': KeyInfo(default=False), + 'name': KeyInfo(), + 'owner': KeyInfo(), + 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), + 'source': KeyInfo(default=''), + }, + ), } diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index f8e9337..958d5dc 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -50,7 +50,9 @@ options: - caps-man provisioning - caps-man security - certificate settings + - interface bonding - interface bridge + - interface bridge mlag - interface bridge port - interface bridge port-controller - interface bridge port-extender @@ -120,6 +122,8 @@ options: - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter + - ipv6 firewall mangle + - ipv6 nd - ipv6 nd prefix default - ipv6 route - ipv6 settings @@ -153,7 +157,10 @@ options: - system ntp server - system package update - system routerboard settings + - system scheduler + - system script - system upgrade mirror + - system ups - system watchdog - tool bandwidth-server - tool e-mail diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index fc57ee0..c8f0d74 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -55,7 +55,9 @@ options: - caps-man provisioning - caps-man security - certificate settings + - interface bonding - interface bridge + - interface bridge mlag - interface bridge port - interface bridge port-controller - interface bridge port-extender @@ -125,6 +127,8 @@ options: - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter + - ipv6 firewall mangle + - ipv6 nd - ipv6 nd prefix default - ipv6 route - ipv6 settings @@ -158,7 +162,10 @@ options: - system ntp server - system package update - system routerboard settings + - system scheduler + - system script - system upgrade mirror + - system ups - system watchdog - tool bandwidth-server - tool e-mail diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 70a5ab6..8478daa 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -220,6 +220,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): '!ingress-priority': None, '!ipsec-policy': None, '!ipv4-options': None, + '!jump-target': None, '!layer7-protocol': None, '!limit': None, '!log': None, @@ -238,6 +239,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): '!protocol': None, '!psd': None, '!random': None, + '!reject-with': None, '!routing-mark': None, '!routing-table': None, '!src-address': None, @@ -304,6 +306,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'ingress-priority': None, 'ipsec-policy': None, 'ipv4-options': None, + 'jump-target': None, 'layer7-protocol': None, 'limit': None, 'log': None, @@ -322,6 +325,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'protocol': None, 'psd': None, 'random': None, + 'reject-with': None, 'routing-mark': None, 'routing-table': None, 'src-address': None, From 309e2b1910002ae7d7bbeab1c7a96f65181cc84a Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Thu, 17 Nov 2022 21:03:42 +0100 Subject: [PATCH 085/365] terminal regex udpate to match the terminal prompt in safe mode (#134) * terminal regex udpate to match the terminal prompt in safe mode Signed-off-by: Tomas Herfert * changelog Signed-off-by: Tomas Herfert * yamllint fix Signed-off-by: Tomas Herfert * Update changelogs/fragments/134-command-safemode.yml Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/134-command-safemode.yml | 3 +++ plugins/terminal/routeros.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/134-command-safemode.yml diff --git a/changelogs/fragments/134-command-safemode.yml b/changelogs/fragments/134-command-safemode.yml new file mode 100644 index 0000000..4482d92 --- /dev/null +++ b/changelogs/fragments/134-command-safemode.yml @@ -0,0 +1,3 @@ +bugfixes: + - "command, facts - commands do not timeout in safe mode anymore + (https://github.com/ansible-collections/community.routeros/pull/134)." diff --git a/plugins/terminal/routeros.py b/plugins/terminal/routeros.py index a2646e3..1d3fa6c 100644 --- a/plugins/terminal/routeros.py +++ b/plugins/terminal/routeros.py @@ -33,7 +33,7 @@ class TerminalModule(TerminalBase): terminal_stdout_re = [ re.compile(br"\x1b<"), - re.compile(br"\[[\w\-\.]+\@[\w\s\-\.\/]+\] ?> ?$"), + re.compile(br"\[[\w\-\.]+\@[\w\s\-\.\/]+\] ?( ?$"), re.compile(br"Please press \"Enter\" to continue!"), re.compile(br"Do you want to see the software license\? \[Y\/n\]: ?"), ] From d1ff3b2730a9302a51cedf8f4c5b94d602c9d888 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 18 Nov 2022 12:55:34 +0100 Subject: [PATCH 086/365] Add more tests for api_info and api_modify (#135) * Add tests for builtin entries. * Add tests for combined default and can_disable. --- tests/unit/plugins/modules/fake_api.py | 13 +- tests/unit/plugins/modules/test_api_info.py | 311 ++++++++++++++++++ tests/unit/plugins/modules/test_api_modify.py | 154 +++++++++ 3 files changed, 477 insertions(+), 1 deletion(-) diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index f50c996..37fae3b 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -132,10 +132,12 @@ def _normalize_entry(entry, path_info): del entry[key] -def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=False): +def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=False, remove_builtin=False): path_info = PATHS[path] if remove_dynamic: values = [entry for entry in values if not entry.get('dynamic', False)] + if remove_builtin: + values = [entry for entry in values if not entry.get('builtin', False)] values = [entry.copy() for entry in values] for entry in values: _normalize_entry(entry, path_info) @@ -178,6 +180,8 @@ class Path(object): raise Exception('Modifying read-only path: add %s' % repr(kwargs)) if '.id' in kwargs: raise Exception('Trying to create new entry with ".id" field: %s' % repr(kwargs)) + if 'dynamic' in kwargs or 'builtin' in kwargs: + raise Exception('Trying to add a dynamic or builtin entry') self._new_id_counter += 1 id = '*NEW%d' % self._new_id_counter entry = { @@ -195,16 +199,23 @@ class Path(object): raise Exception('Modifying read-only path: remove %s' % repr(args)) for id in args: index = self._find_id(id, required=True) + entry = self._values[index] + if entry.get('dynamic', False) or entry.get('builtin', False): + raise Exception('Trying to remove a dynamic or builtin entry') del self._values[index] def update(self, **kwargs): if self._read_only: raise Exception('Modifying read-only path: update %s' % repr(kwargs)) + if 'dynamic' in kwargs or 'builtin' in kwargs: + raise Exception('Trying to update dynamic builtin fields') if self._path_info.single_value: index = 0 else: index = self._find_id(kwargs['.id'], required=True) entry = self._values[index] + if entry.get('dynamic', False) or entry.get('builtin', False): + raise Exception('Trying to update a dynamic or builtin entry') entry.update(kwargs) _normalize_entry(entry, self._path_info) diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 8478daa..ac374dd 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -413,6 +413,128 @@ class TestRouterosApiInfoModule(ModuleTestCase): }, ]) + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_builtin_exclude(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + '.id': '*2000000', + 'name': 'all', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains all interfaces', + }, + { + '.id': '*2000001', + 'name': 'none', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains no interfaces', + }, + { + '.id': '*2000010', + 'name': 'WAN', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': False, + 'comment': 'defconf', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface list', + 'handle_disabled': 'omit', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + '.id': '*2000010', + 'name': 'WAN', + 'include': '', + 'exclude': '', + 'comment': 'defconf', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_builtin_include(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + '.id': '*2000000', + 'name': 'all', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains all interfaces', + }, + { + '.id': '*2000001', + 'name': 'none', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains no interfaces', + }, + { + '.id': '*2000010', + 'name': 'WAN', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': False, + 'comment': 'defconf', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface list', + 'handle_disabled': 'omit', + 'include_builtin': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + '.id': '*2000000', + 'name': 'all', + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains all interfaces', + }, + { + '.id': '*2000001', + 'name': 'none', + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains no interfaces', + }, + { + '.id': '*2000010', + 'name': 'WAN', + 'include': '', + 'exclude': '', + 'builtin': False, + 'comment': 'defconf', + }, + ]) + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') def test_absent(self, mock_compose_api_path): mock_compose_api_path.return_value = [ @@ -501,3 +623,192 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'server': 'all', }, ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_default_disable_1(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + '.id': '*10', + 'name': 'gre-tunnel3', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.1', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*11', + 'name': 'gre-tunnel4', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.2', + 'keepalive': '10s,10', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*12', + 'name': 'gre-tunnel5', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + 'comment': 'foo', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface gre', + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + '.id': '*10', + 'name': 'gre-tunnel3', + 'remote-address': '192.168.1.1', + '!comment': None, + '!ipsec-secret': None, + '!keepalive': None, + }, + { + '.id': '*11', + 'name': 'gre-tunnel4', + 'remote-address': '192.168.1.2', + '!comment': None, + '!ipsec-secret': None, + }, + { + '.id': '*12', + 'name': 'gre-tunnel5', + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'comment': 'foo', + '!ipsec-secret': None, + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_default_disable_2(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + '.id': '*10', + 'name': 'gre-tunnel3', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.1', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*11', + 'name': 'gre-tunnel4', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.2', + 'keepalive': '10s,10', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*12', + 'name': 'gre-tunnel5', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + 'comment': 'foo', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface gre', + 'handle_disabled': 'omit', + 'hide_defaults': False, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + '.id': '*10', + 'name': 'gre-tunnel3', + 'mtu': 'auto', + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.1', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'disabled': False, + }, + { + '.id': '*11', + 'name': 'gre-tunnel4', + 'mtu': 'auto', + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.2', + 'keepalive': '10s,10', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'disabled': False, + }, + { + '.id': '*12', + 'name': 'gre-tunnel5', + 'mtu': 'auto', + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'disabled': False, + 'comment': 'foo', + }, + ]) diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index 2d70c43..2c6e0bd 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -161,6 +161,97 @@ START_IP_DHCP_SEVER_LEASE = [ START_IP_DHCP_SEVER_LEASE_OLD_DATA = massage_expected_result_data(START_IP_DHCP_SEVER_LEASE, ('ip', 'dhcp-server', 'lease')) +START_INTERFACE_LIST = [ + { + '.id': '*2000000', + 'name': 'all', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains all interfaces', + }, + { + '.id': '*2000001', + 'name': 'none', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': True, + 'comment': 'contains no interfaces', + }, + { + '.id': '*2000010', + 'name': 'WAN', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': False, + 'comment': 'defconf', + }, + { + '.id': '*2000011', + 'name': 'Foo', + 'dynamic': False, + 'include': '', + 'exclude': '', + 'builtin': False, + 'comment': '', + }, +] + +START_INTERFACE_LIST_OLD_DATA = massage_expected_result_data(START_INTERFACE_LIST, ('interface', 'list'), remove_builtin=True) + +START_INTERFACE_GRE = [ + { + '.id': '*10', + 'name': 'gre-tunnel3', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.1', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*11', + 'name': 'gre-tunnel4', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '0.0.0.0', + 'remote-address': '192.168.1.2', + 'keepalive': '10s,10', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + }, + { + '.id': '*12', + 'name': 'gre-tunnel5', + 'mtu': 'auto', + 'actual-mtu': 65496, + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'dscp': 'inherit', + 'clamp-tcp-mss': True, + 'dont-fragment': False, + 'allow-fast-path': True, + 'running': True, + 'disabled': False, + 'comment': 'foo', + }, +] + +START_INTERFACE_GRE_OLD_DATA = massage_expected_result_data(START_INTERFACE_GRE, ('interface', 'gre')) + class TestRouterosApiModifyModule(ModuleTestCase): @@ -1650,3 +1741,66 @@ class TestRouterosApiModifyModule(ModuleTestCase): self.assertEqual(result['changed'], False) self.assertEqual(result['old_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) self.assertEqual(result['new_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('interface', 'list'), START_INTERFACE_LIST, read_only=True)) + def test_absent_entries_builtin(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface list', + 'data': [ + { + 'name': 'WAN', + 'comment': 'defconf', + }, + { + 'name': 'Foo', + }, + ], + 'handle_absent_entries': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_INTERFACE_LIST_OLD_DATA) + self.assertEqual(result['new_data'], START_INTERFACE_LIST_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('interface', 'gre'), START_INTERFACE_GRE, read_only=True)) + def test_idempotent_default_disabled(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'interface gre', + 'data': [ + { + 'name': 'gre-tunnel3', + 'remote-address': '192.168.1.1', + '!keepalive': None, + }, + { + 'name': 'gre-tunnel4', + 'remote-address': '192.168.1.2', + }, + { + 'name': 'gre-tunnel5', + 'local-address': '192.168.0.1', + 'remote-address': '192.168.1.3', + 'keepalive': '20s,20', + 'comment': 'foo', + }, + ], + 'handle_absent_entries': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_INTERFACE_GRE_OLD_DATA) + self.assertEqual(result['new_data'], START_INTERFACE_GRE_OLD_DATA) From 14ba81ac60312ffa9ca54c6deb64b4416978b58d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 18 Nov 2022 13:17:00 +0100 Subject: [PATCH 087/365] Release 2.4.0. --- CHANGELOG.rst | 44 +++++++++ changelogs/changelog.yaml | 99 +++++++++++++++++++ changelogs/fragments/120-api.yml | 3 - changelogs/fragments/121-api.yml | 6 -- changelogs/fragments/122-api.yml | 4 - changelogs/fragments/123-api.yml | 3 - changelogs/fragments/124-api.yml | 3 - changelogs/fragments/125-api.yml | 6 -- changelogs/fragments/126-api-capsman.yml | 3 - changelogs/fragments/127-logging.yml | 3 - changelogs/fragments/128-api.yml | 3 - changelogs/fragments/129-api-ipsec.yml | 3 - .../fragments/130-api-modify-builtin.yml | 6 -- changelogs/fragments/131-api.yml | 15 --- changelogs/fragments/133-api.yml | 11 --- changelogs/fragments/134-command-safemode.yml | 3 - changelogs/fragments/2.4.0.yml | 1 - 17 files changed, 143 insertions(+), 73 deletions(-) delete mode 100644 changelogs/fragments/120-api.yml delete mode 100644 changelogs/fragments/121-api.yml delete mode 100644 changelogs/fragments/122-api.yml delete mode 100644 changelogs/fragments/123-api.yml delete mode 100644 changelogs/fragments/124-api.yml delete mode 100644 changelogs/fragments/125-api.yml delete mode 100644 changelogs/fragments/126-api-capsman.yml delete mode 100644 changelogs/fragments/127-logging.yml delete mode 100644 changelogs/fragments/128-api.yml delete mode 100644 changelogs/fragments/129-api-ipsec.yml delete mode 100644 changelogs/fragments/130-api-modify-builtin.yml delete mode 100644 changelogs/fragments/131-api.yml delete mode 100644 changelogs/fragments/133-api.yml delete mode 100644 changelogs/fragments/134-command-safemode.yml delete mode 100644 changelogs/fragments/2.4.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c4c573c..786f4fa 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,50 @@ Community RouterOS Release Notes .. contents:: Topics +v2.4.0 +====== + +Release Summary +--------------- + +Feature release improving the ``api*`` modules. + +Minor Changes +------------- + +- api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers (https://github.com/ansible-collections/community.routeros/pull/124). +- api_info - new parameter ``include_builtin`` which allows to include "builtin" entries that are automatically generated by ROS and cannot be modified by the user (https://github.com/ansible-collections/community.routeros/pull/130). +- api_modify, api_info - support API paths - ``interface bonding``, ``interface bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, ``system script``, ``system ups`` (https://github.com/ansible-collections/community.routeros/pull/133). +- api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man provisioning``, ``caps-man security`` (https://github.com/ansible-collections/community.routeros/pull/126). +- api_modify, api_info - support API paths ``interface list`` and ``interface list member`` (https://github.com/ansible-collections/community.routeros/pull/120). +- api_modify, api_info - support API paths ``interface pppoe-client``, ``interface vlan``, ``interface bridge``, ``interface bridge vlan`` (https://github.com/ansible-collections/community.routeros/pull/125). +- api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` (https://github.com/ansible-collections/community.routeros/pull/129). +- api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` (https://github.com/ansible-collections/community.routeros/pull/123). +- api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify, api_info - support API paths ``system logging``, ``system logging action`` (https://github.com/ansible-collections/community.routeros/pull/127). +- api_modify, api_info - support field ``hw-offload`` for path ``ip firewall filter`` (https://github.com/ansible-collections/community.routeros/pull/121). +- api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, ``packet-mark``, ``packet-size``, ``per-connection-classifier``, ``port``, ``priority``, ``psd``, ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, ``src-address``, ``src-address-list``, ``src-address-type``, ``src-mac-address``, ``src-port``, ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/133). +- api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, ``mdix-enable``, ``poe-out``, ``poe-priority``, ``poe-voltage``, ``power-cycle-interval``, ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). +- api_modify, api_info - support fields ``jump-target``, ``reject-with`` in ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` API path, field ``jump-target`` in ``ip firewall mangle`` API path, field ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, ``reject-with`` in ``ipv6 firewall filter`` API path (https://github.com/ansible-collections/community.routeros/pull/133). +- api_modify, api_info - support for API fields that can be disabled and have default value at the same time, support API paths ``interface gre``, ``interface eoip`` (https://github.com/ansible-collections/community.routeros/pull/128). +- api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify, api_info - support paths ``system ntp client servers`` and ``system ntp server`` available in ROS7, as well as new fields ``servers``, ``mode``, and ``vrf`` for ``system ntp client`` (https://github.com/ansible-collections/community.routeros/pull/122). + +Bugfixes +-------- + +- api_modify - ``ip route`` entry can be defined without the need of ``gateway`` field, which is correct for unreachable/blackhole type of routes (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify - ``queue interface`` path works now (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 firewall address-list`` (https://github.com/ansible-collections/community.routeros/pull/133). +- api_modify, api_info - the default of the field ``ingress-filtering`` in ``interface bridge port`` is now ``true``, which is the default in ROS (https://github.com/ansible-collections/community.routeros/pull/125). +- command, facts - commands do not timeout in safe mode anymore (https://github.com/ansible-collections/community.routeros/pull/134). + +Known Issues +------------ + +- api_modify - when limits for entries in ``queue tree`` are defined as human readable - for example ``25M`` -, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - for example ``25000000`` (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). + v2.3.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index d3615e6..a9bf925 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -255,3 +255,102 @@ releases: - 2.3.1.yml - command-check_mode.yml release_date: '2022-11-06' + 2.4.0: + changes: + bugfixes: + - api_modify - ``ip route`` entry can be defined without the need of ``gateway`` + field, which is correct for unreachable/blackhole type of routes (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify - ``queue interface`` path works now (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 + firewall address-list`` (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - the default of the field ``ingress-filtering`` in ``interface + bridge port`` is now ``true``, which is the default in ROS (https://github.com/ansible-collections/community.routeros/pull/125). + - command, facts - commands do not timeout in safe mode anymore (https://github.com/ansible-collections/community.routeros/pull/134). + known_issues: + - api_modify - when limits for entries in ``queue tree`` are defined as human + readable - for example ``25M`` -, the configuration will be correctly set + in ROS, but the module will indicate the item is changed on every run even + when there was no change done. This is caused by the ROS API which returns + the number in bytes - for example ``25000000`` (which is inconsistent with + the CLI behavior). In order to mitigate that, the limits have to be defined + in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, + ``routing ospf instance``, ``routing ospf interface-template`` paths are not + fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 + (https://github.com/ansible-collections/community.routeros/pull/131). + minor_changes: + - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers + (https://github.com/ansible-collections/community.routeros/pull/124). + - api_info - new parameter ``include_builtin`` which allows to include "builtin" + entries that are automatically generated by ROS and cannot be modified by + the user (https://github.com/ansible-collections/community.routeros/pull/130). + - api_modify, api_info - support API paths - ``interface bonding``, ``interface + bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, + ``system script``, ``system ups`` (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man + configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man provisioning``, + ``caps-man security`` (https://github.com/ansible-collections/community.routeros/pull/126). + - api_modify, api_info - support API paths ``interface list`` and ``interface + list member`` (https://github.com/ansible-collections/community.routeros/pull/120). + - api_modify, api_info - support API paths ``interface pppoe-client``, ``interface + vlan``, ``interface bridge``, ``interface bridge vlan`` (https://github.com/ansible-collections/community.routeros/pull/125). + - api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec + peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` (https://github.com/ansible-collections/community.routeros/pull/129). + - api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` + (https://github.com/ansible-collections/community.routeros/pull/123). + - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, + ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf + area``, ``routing ospf area range``, ``routing ospf instance``, ``routing + ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` + (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - support API paths ``system logging``, ``system logging + action`` (https://github.com/ansible-collections/community.routeros/pull/127). + - api_modify, api_info - support field ``hw-offload`` for path ``ip firewall + filter`` (https://github.com/ansible-collections/community.routeros/pull/121). + - api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, + ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, + ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, + ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, + ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, + ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, + ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, ``packet-mark``, + ``packet-size``, ``per-connection-classifier``, ``port``, ``priority``, ``psd``, + ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, ``src-address``, + ``src-address-list``, ``src-address-type``, ``src-mac-address``, ``src-port``, + ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, + ``mdix-enable``, ``poe-out``, ``poe-priority``, ``poe-voltage``, ``power-cycle-interval``, + ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` + for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). + - api_modify, api_info - support fields ``jump-target``, ``reject-with`` in + ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` + API path, field ``jump-target`` in ``ip firewall mangle`` API path, field + ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, + ``reject-with`` in ``ipv6 firewall filter`` API path (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support for API fields that can be disabled and have + default value at the same time, support API paths ``interface gre``, ``interface + eoip`` (https://github.com/ansible-collections/community.routeros/pull/128). + - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, + ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path + (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - support paths ``system ntp client servers`` and ``system + ntp server`` available in ROS7, as well as new fields ``servers``, ``mode``, + and ``vrf`` for ``system ntp client`` (https://github.com/ansible-collections/community.routeros/pull/122). + release_summary: Feature release improving the ``api*`` modules. + fragments: + - 120-api.yml + - 121-api.yml + - 122-api.yml + - 123-api.yml + - 124-api.yml + - 125-api.yml + - 126-api-capsman.yml + - 127-logging.yml + - 128-api.yml + - 129-api-ipsec.yml + - 130-api-modify-builtin.yml + - 131-api.yml + - 133-api.yml + - 134-command-safemode.yml + - 2.4.0.yml + release_date: '2022-11-18' diff --git a/changelogs/fragments/120-api.yml b/changelogs/fragments/120-api.yml deleted file mode 100644 index 61fbe3b..0000000 --- a/changelogs/fragments/120-api.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``interface list`` and ``interface list member`` - (https://github.com/ansible-collections/community.routeros/pull/120). diff --git a/changelogs/fragments/121-api.yml b/changelogs/fragments/121-api.yml deleted file mode 100644 index 0452551..0000000 --- a/changelogs/fragments/121-api.yml +++ /dev/null @@ -1,6 +0,0 @@ -minor_changes: - - api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, ``mdix-enable``, ``poe-out``, ``poe-priority``, - ``poe-voltage``, ``power-cycle-interval``, ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` - for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). - - api_modify, api_info - support field ``hw-offload`` for path ``ip firewall filter`` - (https://github.com/ansible-collections/community.routeros/pull/121). diff --git a/changelogs/fragments/122-api.yml b/changelogs/fragments/122-api.yml deleted file mode 100644 index 399dabe..0000000 --- a/changelogs/fragments/122-api.yml +++ /dev/null @@ -1,4 +0,0 @@ -minor_changes: - - api_modify, api_info - support paths ``system ntp client servers`` and ``system ntp server`` available in ROS7, - as well as new fields ``servers``, ``mode``, and ``vrf`` for ``system ntp client`` - (https://github.com/ansible-collections/community.routeros/pull/122). diff --git a/changelogs/fragments/123-api.yml b/changelogs/fragments/123-api.yml deleted file mode 100644 index 561a6ed..0000000 --- a/changelogs/fragments/123-api.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` - (https://github.com/ansible-collections/community.routeros/pull/123). diff --git a/changelogs/fragments/124-api.yml b/changelogs/fragments/124-api.yml deleted file mode 100644 index 6299cea..0000000 --- a/changelogs/fragments/124-api.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers - (https://github.com/ansible-collections/community.routeros/pull/124). diff --git a/changelogs/fragments/125-api.yml b/changelogs/fragments/125-api.yml deleted file mode 100644 index 582623e..0000000 --- a/changelogs/fragments/125-api.yml +++ /dev/null @@ -1,6 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``interface pppoe-client``, ``interface vlan``, ``interface bridge``, ``interface bridge vlan`` - (https://github.com/ansible-collections/community.routeros/pull/125). -bugfixes: - - api_modify, api_info - the default of the field ``ingress-filtering`` in ``interface bridge port`` is now ``true``, which is the default in ROS - (https://github.com/ansible-collections/community.routeros/pull/125). diff --git a/changelogs/fragments/126-api-capsman.yml b/changelogs/fragments/126-api-capsman.yml deleted file mode 100644 index 9dae1f8..0000000 --- a/changelogs/fragments/126-api-capsman.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man provisioning``, ``caps-man security`` - (https://github.com/ansible-collections/community.routeros/pull/126). diff --git a/changelogs/fragments/127-logging.yml b/changelogs/fragments/127-logging.yml deleted file mode 100644 index 59245d2..0000000 --- a/changelogs/fragments/127-logging.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``system logging``, ``system logging action`` - (https://github.com/ansible-collections/community.routeros/pull/127). diff --git a/changelogs/fragments/128-api.yml b/changelogs/fragments/128-api.yml deleted file mode 100644 index 6bcc4b7..0000000 --- a/changelogs/fragments/128-api.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support for API fields that can be disabled and have default value at the same time, support API paths ``interface gre``, ``interface eoip`` - (https://github.com/ansible-collections/community.routeros/pull/128). diff --git a/changelogs/fragments/129-api-ipsec.yml b/changelogs/fragments/129-api-ipsec.yml deleted file mode 100644 index c13b7a7..0000000 --- a/changelogs/fragments/129-api-ipsec.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` - (https://github.com/ansible-collections/community.routeros/pull/129). diff --git a/changelogs/fragments/130-api-modify-builtin.yml b/changelogs/fragments/130-api-modify-builtin.yml deleted file mode 100644 index 01d8b55..0000000 --- a/changelogs/fragments/130-api-modify-builtin.yml +++ /dev/null @@ -1,6 +0,0 @@ -minor_changes: - - api_info - new parameter ``include_builtin`` which allows to include "builtin" entries that are automatically generated by ROS and cannot be modified by the user - (https://github.com/ansible-collections/community.routeros/pull/130). -trivial: - - api_modify - ignore ``builtin`` entries - (https://github.com/ansible-collections/community.routeros/pull/130). diff --git a/changelogs/fragments/131-api.yml b/changelogs/fragments/131-api.yml deleted file mode 100644 index 8e2ad1c..0000000 --- a/changelogs/fragments/131-api.yml +++ /dev/null @@ -1,15 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` - (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path - (https://github.com/ansible-collections/community.routeros/pull/131). -known_issues: - - api_modify - when limits for entries in ``queue tree`` are defined as human readable - for example ``25M`` -, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - for example ``25000000`` (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI) - (https://github.com/ansible-collections/community.routeros/pull/131). - - "api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 - (https://github.com/ansible-collections/community.routeros/pull/131)." -bugfixes: - - "api_modify - ``queue interface`` path works now - (https://github.com/ansible-collections/community.routeros/pull/131)." - - "api_modify - ``ip route`` entry can be defined without the need of ``gateway`` field, which is correct for unreachable/blackhole type of routes - (https://github.com/ansible-collections/community.routeros/pull/131)." diff --git a/changelogs/fragments/133-api.yml b/changelogs/fragments/133-api.yml deleted file mode 100644 index ecd8a62..0000000 --- a/changelogs/fragments/133-api.yml +++ /dev/null @@ -1,11 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths - ``interface bonding``, ``interface bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, ``system script``, ``system ups`` - (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - support fields ``jump-target``, ``reject-with`` in ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` API path, field ``jump-target`` in ``ip firewall mangle`` API path, field ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, ``reject-with`` in ``ipv6 firewall filter`` API path - (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, ``packet-mark``, ``packet-size``, ``per-connection-classifier``, ``port``, ``priority``, ``psd``, ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, ``src-address``, ``src-address-list``, ``src-address-type``, ``src-mac-address``, ``src-port``, ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall nat`` path - (https://github.com/ansible-collections/community.routeros/pull/133). - -bugfixes: - - api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 firewall address-list`` - (https://github.com/ansible-collections/community.routeros/pull/133). diff --git a/changelogs/fragments/134-command-safemode.yml b/changelogs/fragments/134-command-safemode.yml deleted file mode 100644 index 4482d92..0000000 --- a/changelogs/fragments/134-command-safemode.yml +++ /dev/null @@ -1,3 +0,0 @@ -bugfixes: - - "command, facts - commands do not timeout in safe mode anymore - (https://github.com/ansible-collections/community.routeros/pull/134)." diff --git a/changelogs/fragments/2.4.0.yml b/changelogs/fragments/2.4.0.yml deleted file mode 100644 index 5180a2f..0000000 --- a/changelogs/fragments/2.4.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release improving the ``api*`` modules. From 0f5ac3f061d60648ba582f7257ad5492cfd30664 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Nov 2022 09:38:34 +0100 Subject: [PATCH 088/365] Add GH Pages publishing. --- .github/workflows/docs-pr.yml | 35 ++++++++++++++++++++++++--- .github/workflows/docs-push.yml | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/docs-push.yml diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 84adc61..726f8dc 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -5,12 +5,15 @@ name: Collection Docs concurrency: - group: docs-${{ github.head_ref }} + group: docs-pr-${{ github.head_ref }} cancel-in-progress: true on: pull_request_target: types: [opened, synchronize, reopened, closed] +env: + GHP_BASE_URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }} + jobs: build-docs: permissions: @@ -18,13 +21,30 @@ jobs: name: Build Ansible Docs uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main with: + init-lenient: false init-fail-on-error: true + squash-hierarchy: true + render-file-line: '> * `$` [$](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr/${{ github.event.number }}/$)' + + publish-docs-gh-pages: + # for now we won't run this on forks + if: github.repository == 'ansible-collections/community.routeros' + permissions: + contents: write + needs: [build-docs] + name: Publish Ansible Docs + uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main + with: + artifact-name: ${{ needs.build-docs.outputs.artifact-name }} + action: ${{ (github.event.action == 'closed' || needs.build-docs.outputs.changed != 'true') && 'teardown' || 'publish' }} + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} comment: permissions: pull-requests: write runs-on: ubuntu-latest - needs: build-docs + needs: [build-docs, publish-docs-gh-pages] name: PR comments steps: - name: PR comment @@ -42,13 +62,20 @@ jobs: Thank you for contribution!✨ - This PR has been merged and your docs changes will be incorporated when they are next published. + This PR has been merged and the docs are now incorporated into `main`: + ${{ env.GHP_BASE_URL }}/branch/main body: | ## Docs Build 📝 Thank you for contribution!✨ - The docsite for **this PR** is available for download as an artifact from this run: + The docs for **this PR** have been published here: + ${{ env.GHP_BASE_URL }}/pr/${{ github.event.number }} + + You can compare to the docs for the `main` branch here: + ${{ env.GHP_BASE_URL }}/branch/main + + The docsite for **this PR** is also available for download as an artifact from this run: ${{ needs.build-docs.outputs.artifact-url }} File changes: diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml new file mode 100644 index 0000000..8a7f156 --- /dev/null +++ b/.github/workflows/docs-push.yml @@ -0,0 +1,43 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +name: Collection Docs +concurrency: + group: docs-push-${{ github.sha }} + cancel-in-progress: true +on: + push: + branches: + - main + - stable-* + tags: + - '*' + # Run CI once per day (at 05:15 UTC) + schedule: + - cron: '15 5 * * *' + +jobs: + build-docs: + permissions: + contents: read + name: Build Ansible Docs + uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main + with: + init-lenient: false + init-fail-on-error: true + squash-hierarchy: true + + publish-docs-gh-pages: + # for now we won't run this on forks + if: github.repository == 'ansible-collections/community.routeros' + permissions: + contents: write + needs: [build-docs] + name: Publish Ansible Docs + uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main + with: + artifact-name: ${{ needs.build-docs.outputs.artifact-name }} + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 61b28ba22d6355358afc54f600bc4a45e631aa4a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Nov 2022 10:15:19 +0100 Subject: [PATCH 089/365] Reference documentation in README. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 379ae21..fb7ad63 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,16 @@ The collection supports the `network_cli` connection. Please note that `community.routeros.api` module does **not** support Windows jump hosts! +## Collection Documentation + +Browsing the [**latest** collection documentation](https://docs.ansible.com/ansible/latest/collections/community/routeros) will show docs for the _latest version released in the Ansible package_, not the latest version of the collection released on Galaxy. + +Browsing the [**devel** collection documentation](https://docs.ansible.com/ansible/devel/collections/community/routeros) shows docs for the _latest version released on Galaxy_. + +We also separately publish [**latest commit** collection documentation](https://ansible-collections.github.io/community.routeros/branch/main/) which shows docs for the _latest commit in the `main` branch_. + +If you use the Ansible package and do not update collections independently, use **latest**. If you install or update this collection directly from Galaxy, use **devel**. If you are looking to contribute, use **latest commit**. + ## Included content - `community.routeros.api` From 38e00caedb425f3498b7aeab382a213e3fc7fa98 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Nov 2022 22:06:43 +0100 Subject: [PATCH 090/365] Directly reference filters. (#136) --- docs/docsite/rst/quoting.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docsite/rst/quoting.rst b/docs/docsite/rst/quoting.rst index 785c7f8..3091fc8 100644 --- a/docs/docsite/rst/quoting.rst +++ b/docs/docsite/rst/quoting.rst @@ -12,8 +12,8 @@ When using the :ref:`community.routeros.command module ` quotes an argument value: ``'this is a "comment"' | community.routeros.quote_argument_value == '"this is a \\"comment\\""'``. +- The :ref:`community.routeros.quote_argument filter ` quotes an argument with or without a value: ``'comment=this is a "comment"' | community.routeros.quote_argument == 'comment="this is a \\"comment\\""'``. +- The :ref:`community.routeros.join filter ` quotes a list of arguments and joins them to one string: ``['foo=bar', 'comment=foo is bar'] | community.routeros.join == 'foo=bar comment="foo is bar"'``. +- The :ref:`community.routeros.split filter ` splits a command into a list of arguments (with or without values): ``'foo=bar comment="foo is bar"' | community.routeros.split == ['foo=bar', 'comment=foo is bar']`` +- The :ref:`community.routeros.list_to_dict filter ` splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: ``require_assignment`` (default value ``true``) allows to accept arguments without values when set to ``false``; and ``skip_empty_values`` (default value ``false``) allows to skip arguments whose value is empty. From 4ed2fc82e5e897f3347df183cc4a9e36677ad807 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 27 Nov 2022 17:44:37 +0100 Subject: [PATCH 091/365] Include collection name into docs workflows. --- .github/workflows/docs-pr.yml | 1 + .github/workflows/docs-push.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 726f8dc..6acb561 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -21,6 +21,7 @@ jobs: name: Build Ansible Docs uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main with: + collection-name: community.routeros init-lenient: false init-fail-on-error: true squash-hierarchy: true diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index 8a7f156..466234e 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -25,6 +25,7 @@ jobs: name: Build Ansible Docs uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main with: + collection-name: community.routeros init-lenient: false init-fail-on-error: true squash-hierarchy: true From 4376906ed0c946c9605bfafb2449670e580309ec Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Tue, 29 Nov 2022 13:06:02 +0100 Subject: [PATCH 092/365] Paths (#137) * support for "interface ethernet poe" and "interface vrrp" Signed-off-by: Tomas Herfert * support "interface gre6" path Signed-off-by: Tomas Herfert * ip dhcp-server - fix Signed-off-by: Tomas Herfert * docs & changelog Signed-off-by: Tomas Herfert * support for "interface ethernet poe" and "interface vrrp" Signed-off-by: Tomas Herfert * support "interface gre6" path Signed-off-by: Tomas Herfert * ip dhcp-server - fix Signed-off-by: Tomas Herfert * docs & changelog Signed-off-by: Tomas Herfert * Apply suggestions from code review Co-authored-by: Felix Fontein Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert Co-authored-by: Felix Fontein --- changelogs/fragments/137-api.yml | 5 +++ plugins/module_utils/_api_data.py | 74 ++++++++++++++++++++++++++++++- plugins/modules/api_info.py | 3 ++ plugins/modules/api_modify.py | 3 ++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/137-api.yml diff --git a/changelogs/fragments/137-api.yml b/changelogs/fragments/137-api.yml new file mode 100644 index 0000000..8372c29 --- /dev/null +++ b/changelogs/fragments/137-api.yml @@ -0,0 +1,5 @@ +--- +minor_changes: + - api_info, api_modify - support API paths ``interface ethernet poe``, ``interface gre6``, ``interface vrrp`` and also support all previously missing fields of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). +bugfixes: + - api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 133048c..04f1f2b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -199,6 +199,21 @@ PATHS = { 'tx-flow-control': KeyInfo(default='off'), }, ), + ('interface', 'ethernet', 'poe'): APIData( + fixed_entries=True, + fully_understood=True, + primary_keys=('name', ), + fields={ + 'name': KeyInfo(), + 'poe-out': KeyInfo(default='auto-on'), + 'poe-priority': KeyInfo(default=10), + 'poe-voltage': KeyInfo(default='auto'), + 'power-cycle-interval': KeyInfo(default='none'), + 'power-cycle-ping-address': KeyInfo(can_disable=True), + 'power-cycle-ping-enabled': KeyInfo(default=False), + 'power-cycle-ping-timeout': KeyInfo(can_disable=True), + } + ), ('interface', 'gre'): APIData( fully_understood=True, primary_keys=('name', ), @@ -217,6 +232,22 @@ PATHS = { 'remote-address': KeyInfo(required=True), }, ), + ('interface', 'gre6'): APIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='::'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + }, + ), ('interface', 'list'): APIData( primary_keys=('name', ), fully_understood=True, @@ -292,6 +323,33 @@ PATHS = { 'vlan-id': KeyInfo(required=True), }, ), + ('interface', 'vrrp'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'authentication': KeyInfo(default='none'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'group-master': KeyInfo(default=''), + 'interface': KeyInfo(required=True), + 'interval': KeyInfo(default='1s'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'on-backup': KeyInfo(default=''), + 'on-fail': KeyInfo(default=''), + 'on-master': KeyInfo(default=''), + 'password': KeyInfo(default=''), + 'preemption-mode': KeyInfo(default=True), + 'priority': KeyInfo(default=100), + 'remote-address': KeyInfo(), + 'sync-connection-tracking': KeyInfo(default=False), + 'v3-protocol': KeyInfo(default='ipv4'), + 'version': KeyInfo(default=3), + 'vrid': KeyInfo(default=1), + }, + ), ('interface', 'wireless', 'security-profiles'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -504,13 +562,27 @@ PATHS = { fully_understood=True, primary_keys=('name', ), fields={ - 'address-pool': KeyInfo(required=True), + 'address-pool': KeyInfo(default='static-only'), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'always-broadcast': KeyInfo(can_disable=True, remove_value=False), 'authoritative': KeyInfo(default=True), + 'bootp-lease-time': KeyInfo(default='forever'), + 'bootp-support': KeyInfo(can_disable=True, remove_value='static'), + 'client-mac-limit': KeyInfo(can_disable=True, remove_value='unlimited'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'conflict-detection': KeyInfo(can_disable=True, remove_value=True), + 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), + 'dhcp-option-set': KeyInfo(can_disable=True, remove_value='none'), 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), 'interface': KeyInfo(required=True), 'lease-script': KeyInfo(default=''), 'lease-time': KeyInfo(default='10m'), 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'relay': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'server-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'use-framed-as-classless': KeyInfo(can_disable=True, remove_value=True), 'use-radius': KeyInfo(default=False), }, ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 958d5dc..e354fda 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -61,9 +61,11 @@ options: - interface detect-internet - interface eoip - interface ethernet + - interface ethernet poe - interface ethernet switch - interface ethernet switch port - interface gre + - interface gre6 - interface l2tp-server server - interface list - interface list member @@ -72,6 +74,7 @@ options: - interface pptp-server server - interface sstp-server server - interface vlan + - interface vrrp - interface wireless align - interface wireless cap - interface wireless sniffer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index c8f0d74..45d7f65 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -66,9 +66,11 @@ options: - interface detect-internet - interface eoip - interface ethernet + - interface ethernet poe - interface ethernet switch - interface ethernet switch port - interface gre + - interface gre6 - interface l2tp-server server - interface list - interface list member @@ -77,6 +79,7 @@ options: - interface pptp-server server - interface sstp-server server - interface vlan + - interface vrrp - interface wireless align - interface wireless cap - interface wireless sniffer From 338a8f2cd68c2729df290f9ace064ac84eb0b579 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 1 Dec 2022 23:15:37 +0100 Subject: [PATCH 093/365] Switch CI from ubuntu-latest to ubuntu-20.04 to avoid problems with ansible-test from ansible-core 2.12, 2.13, 2.14. (#138) --- .github/workflows/ansible-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 1c9550f..127897c 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -33,7 +33,7 @@ jobs: - stable-2.13 - stable-2.14 - devel - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Perform sanity testing uses: ansible-community/ansible-test-gh-action@release/v1 @@ -46,7 +46,7 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils units: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 name: Units (Ⓐ${{ matrix.ansible }}) strategy: # As soon as the first unit test fails, cancel the others to free up the CI queue @@ -75,7 +75,7 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils integration: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: fail-fast: false From f58727e53ba1108ede304f9e880ee1cfa9606d39 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 2 Dec 2022 08:49:13 +0100 Subject: [PATCH 094/365] Only use ubuntu-20.04 if necessary. (#139) --- .github/workflows/ansible-test.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 127897c..1407bff 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -33,7 +33,15 @@ jobs: - stable-2.13 - stable-2.14 - devel - runs-on: ubuntu-20.04 + # Ansible-test on various stable branches does not yet work well with cgroups v2. + # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 + # image for these stable branches. The list of branches where this is necessary will + # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 + # for the latest list. + runs-on: >- + ${{ contains(fromJson( + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} steps: - name: Perform sanity testing uses: ansible-community/ansible-test-gh-action@release/v1 @@ -46,7 +54,15 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils units: - runs-on: ubuntu-20.04 + # Ansible-test on various stable branches does not yet work well with cgroups v2. + # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 + # image for these stable branches. The list of branches where this is necessary will + # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 + # for the latest list. + runs-on: >- + ${{ contains(fromJson( + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: Units (Ⓐ${{ matrix.ansible }}) strategy: # As soon as the first unit test fails, cancel the others to free up the CI queue @@ -75,7 +91,15 @@ jobs: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils integration: - runs-on: ubuntu-20.04 + # Ansible-test on various stable branches does not yet work well with cgroups v2. + # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 + # image for these stable branches. The list of branches where this is necessary will + # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 + # for the latest list. + runs-on: >- + ${{ contains(fromJson( + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: fail-fast: false From 78f1236942ce0265554c2cccf9d4d45fd8766194 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 4 Dec 2022 13:09:32 +0100 Subject: [PATCH 095/365] Prepare 2.5.0 release. --- changelogs/fragments/2.5.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.5.0.yml diff --git a/changelogs/fragments/2.5.0.yml b/changelogs/fragments/2.5.0.yml new file mode 100644 index 0000000..80287c3 --- /dev/null +++ b/changelogs/fragments/2.5.0.yml @@ -0,0 +1 @@ +release_summary: Feature and bugfix release. diff --git a/galaxy.yml b/galaxy.yml index 2722bae..c9547fa 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.4.0 +version: 2.5.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 215576fa1b743018bf85d035fb8c5b7311dd3fc2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 4 Dec 2022 13:14:41 +0100 Subject: [PATCH 096/365] Release 2.5.0. --- CHANGELOG.rst | 18 ++++++++++++++++++ changelogs/changelog.yaml | 14 ++++++++++++++ changelogs/fragments/137-api.yml | 5 ----- changelogs/fragments/2.5.0.yml | 1 - 4 files changed, 32 insertions(+), 6 deletions(-) delete mode 100644 changelogs/fragments/137-api.yml delete mode 100644 changelogs/fragments/2.5.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 786f4fa..7fc8d04 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,24 @@ Community RouterOS Release Notes .. contents:: Topics +v2.5.0 +====== + +Release Summary +--------------- + +Feature and bugfix release. + +Minor Changes +------------- + +- api_info, api_modify - support API paths ``interface ethernet poe``, ``interface gre6``, ``interface vrrp`` and also support all previously missing fields of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). + +Bugfixes +-------- + +- api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). + v2.4.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index a9bf925..76493f3 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -354,3 +354,17 @@ releases: - 134-command-safemode.yml - 2.4.0.yml release_date: '2022-11-18' + 2.5.0: + changes: + bugfixes: + - api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` + is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). + minor_changes: + - api_info, api_modify - support API paths ``interface ethernet poe``, ``interface + gre6``, ``interface vrrp`` and also support all previously missing fields + of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). + release_summary: Feature and bugfix release. + fragments: + - 137-api.yml + - 2.5.0.yml + release_date: '2022-12-04' diff --git a/changelogs/fragments/137-api.yml b/changelogs/fragments/137-api.yml deleted file mode 100644 index 8372c29..0000000 --- a/changelogs/fragments/137-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -minor_changes: - - api_info, api_modify - support API paths ``interface ethernet poe``, ``interface gre6``, ``interface vrrp`` and also support all previously missing fields of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). -bugfixes: - - api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). diff --git a/changelogs/fragments/2.5.0.yml b/changelogs/fragments/2.5.0.yml deleted file mode 100644 index 80287c3..0000000 --- a/changelogs/fragments/2.5.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature and bugfix release. From 5fa47579afde73151454d507256406cc7536ed2a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 7 Dec 2022 13:21:10 +0100 Subject: [PATCH 097/365] Backports to stable-2.13 and stable-2.14 have been merged. (#140) https://github.com/ansible/ansible/pull/79538 https://github.com/ansible/ansible/pull/79507 --- .github/workflows/ansible-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 1407bff..f37a8db 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -40,7 +40,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} steps: - name: Perform sanity testing @@ -61,7 +61,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: Units (Ⓐ${{ matrix.ansible }}) strategy: @@ -98,7 +98,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12", "stable-2.13", "stable-2.14"]' + '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: From f935a41b8a3209aa465e87452ed1cb4e0466d576 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 7 Dec 2022 19:54:25 +0100 Subject: [PATCH 098/365] Allow triggering docs workflow manually. --- .github/workflows/docs-push.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index 466234e..bff6bad 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -17,6 +17,8 @@ on: # Run CI once per day (at 05:15 UTC) schedule: - cron: '15 5 * * *' + # Allow manual trigger (for newer antsibull-docs, sphinx-ansible-theme, ... versions) + workflow_dispatch: jobs: build-docs: From d37ec11ac507f545fefda3380c69080b8ac7a569 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 17 Dec 2022 19:39:03 +0100 Subject: [PATCH 099/365] The ansible-test patch has been backported to stable-2.12. --- .github/workflows/ansible-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index f37a8db..824fdda 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -40,7 +40,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' + '["stable-2.9", "stable-2.10", "stable-2.11"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} steps: - name: Perform sanity testing @@ -61,7 +61,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' + '["stable-2.9", "stable-2.10", "stable-2.11"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: Units (Ⓐ${{ matrix.ansible }}) strategy: @@ -98,7 +98,7 @@ jobs: # for the latest list. runs-on: >- ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11", "stable-2.12"]' + '["stable-2.9", "stable-2.10", "stable-2.11"]' ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: From 282439b356fc6e0b0bf3335aa19f99209b9e7a0e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 18 Dec 2022 09:51:43 +0100 Subject: [PATCH 100/365] Switch to my fork of ansible-test-gh-action. --- .github/workflows/ansible-test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 824fdda..9f46e08 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -44,7 +44,7 @@ jobs: ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} steps: - name: Perform sanity testing - uses: ansible-community/ansible-test-gh-action@release/v1 + uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} testing-type: sanity @@ -81,7 +81,7 @@ jobs: - name: >- Perform unit testing against Ansible version ${{ matrix.ansible }} - uses: ansible-community/ansible-test-gh-action@release/v1 + uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} testing-type: units @@ -145,9 +145,12 @@ jobs: Perform integration testing against Ansible version ${{ matrix.ansible }} under Python ${{ matrix.python }} - uses: ansible-community/ansible-test-gh-action@release/v1 + uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} + integration-continue-on-error: 'false' + integration-diff: 'false' + integration-retry-on-error: 'true' # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) pre-test-cmd: |- git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon From 8e3b19759d436f0bece8a7e52bc82ada25d0ac4e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 18 Dec 2022 21:50:43 +0100 Subject: [PATCH 101/365] Improve docsite build. --- .github/workflows/docs-pr.yml | 6 ++++++ .github/workflows/docs-push.yml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 6acb561..4b3f1f3 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -25,6 +25,12 @@ jobs: init-lenient: false init-fail-on-error: true squash-hierarchy: true + init-project: Community.Routeros Collection + init-copyright: Community.Routeros Contributors + init-title: Community.Routeros Collection Documentation + init-html-short-title: Community.Routeros Collection Docs + init-extra-html-theme-options: | + documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/ render-file-line: '> * `$` [$](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr/${{ github.event.number }}/$)' publish-docs-gh-pages: diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index bff6bad..7408bbb 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -31,6 +31,12 @@ jobs: init-lenient: false init-fail-on-error: true squash-hierarchy: true + init-project: Community.Routeros Collection + init-copyright: Community.Routeros Contributors + init-title: Community.Routeros Collection Documentation + init-html-short-title: Community.Routeros Collection Docs + init-extra-html-theme-options: | + documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/ publish-docs-gh-pages: # for now we won't run this on forks From 62da7dd4e3d7cafb27c1b052b440fe381a405d80 Mon Sep 17 00:00:00 2001 From: Andrei Costescu Date: Tue, 27 Dec 2022 21:41:42 +0100 Subject: [PATCH 102/365] Add wireguard interface and peers (#143) * Add wireguard interface and peers * Add changelog fragment --- changelogs/fragments/143-add-wireguard.yml | 2 ++ plugins/module_utils/_api_data.py | 27 ++++++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 33 insertions(+) create mode 100644 changelogs/fragments/143-add-wireguard.yml diff --git a/changelogs/fragments/143-add-wireguard.yml b/changelogs/fragments/143-add-wireguard.yml new file mode 100644 index 0000000..a098092 --- /dev/null +++ b/changelogs/fragments/143-add-wireguard.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - support API paths ``interface wireguard``, ``interface wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 04f1f2b..9d4b4c8 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1150,6 +1150,33 @@ PATHS = { 'verify-client-certificate': KeyInfo(default='no'), }, ), + ('interface', 'wireguard'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'listen-port': KeyInfo(), + 'mtu': KeyInfo(default=1420), + 'name': KeyInfo(), + 'private-key': KeyInfo(), + }, + ), + ('interface', 'wireguard', 'peers'): APIData( + fully_understood=True, + primary_keys=('public-key', 'interface'), + fields={ + 'allowed-address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'endpoint-address': KeyInfo(), + 'endpoint-port': KeyInfo(default=0), + 'interface': KeyInfo(), + 'persistent-keepalive': KeyInfo(), + 'preshared-key': KeyInfo(), + 'public-key': KeyInfo(), + }, + ), ('interface', 'wireless', 'align'): APIData( single_value=True, fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index e354fda..9d94088 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -75,6 +75,8 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wireguard + - interface wireguard peers - interface wireless align - interface wireless cap - interface wireless sniffer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 45d7f65..d03a860 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -80,6 +80,8 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wireguard + - interface wireguard peers - interface wireless align - interface wireless cap - interface wireless sniffer From 586edbc2117cdc79a7194137ef4dd6292558dfdb Mon Sep 17 00:00:00 2001 From: Andrei Costescu Date: Thu, 29 Dec 2022 08:51:40 +0100 Subject: [PATCH 103/365] Add regexp field to ip dns static (#142) * Add regexp field to "ip dns static" * Change test_invalid_required_missing to use "ip dhcp-server" "ip dns static" requires name or regexp so it cannot be used in this test. * Add required_one_of attribute to APIData Used by "ip dns static" which requires either "name" or "regexp. * Add mutually_exclusive attribute to APIData Used by "ip dns static" where only one of "name" or "regexp" can be used. * Add changelog fragment --- changelogs/fragments/142-dns-regexp.yml | 6 +++ plugins/module_utils/_api_data.py | 24 +++++++++++- plugins/modules/api_modify.py | 18 +++++++++ .../plugins/module_utils/test__api_data.py | 16 ++++++++ tests/unit/plugins/modules/test_api_modify.py | 38 ++++++++++++++++++- 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/142-dns-regexp.yml diff --git a/changelogs/fragments/142-dns-regexp.yml b/changelogs/fragments/142-dns-regexp.yml new file mode 100644 index 0000000..b7538ac --- /dev/null +++ b/changelogs/fragments/142-dns-regexp.yml @@ -0,0 +1,6 @@ +minor_changes: + - api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + +bugfixes: + - api_modify, api_info - do not crash if router contains ``regexp`` DNS entries in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9d4b4c8..038ddef 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -13,6 +13,8 @@ __metaclass__ = type class APIData(object): def __init__(self, primary_keys=None, stratify_keys=None, + required_one_of=None, + mutually_exclusive=None, has_identifier=False, single_value=False, unknown_mechanism=False, @@ -25,6 +27,8 @@ class APIData(object): raise ValueError('unknown_mechanism and fully_understood cannot be combined') self.primary_keys = primary_keys self.stratify_keys = stratify_keys + self.required_one_of = required_one_of or [] + self.mutually_exclusive = mutually_exclusive or [] self.has_identifier = has_identifier self.single_value = single_value self.unknown_mechanism = unknown_mechanism @@ -43,6 +47,20 @@ class APIData(object): for sk in stratify_keys: if sk not in fields: raise ValueError('Stratify key {sk} must be in fields!'.format(sk=sk)) + if required_one_of: + for index, require_list in enumerate(required_one_of): + if not isinstance(require_list, list): + raise ValueError('Require one of element at index #{index} must be a list!'.format(index=index + 1)) + for rk in require_list: + if rk not in fields: + raise ValueError('Require one of key {rk} must be in fields!'.format(rk=rk)) + if mutually_exclusive: + for index, exclusive_list in enumerate(mutually_exclusive): + if not isinstance(exclusive_list, list): + raise ValueError('Mutually exclusive element at index #{index} must be a list!'.format(index=index + 1)) + for ek in exclusive_list: + if ek not in fields: + raise ValueError('Mutually exclusive key {ek} must be in fields!'.format(ek=ek)) class KeyInfo(object): @@ -1356,7 +1374,8 @@ PATHS = { ), ('ip', 'dns', 'static'): APIData( fully_understood=True, - stratify_keys=('name', ), + required_one_of=[['name', 'regexp']], + mutually_exclusive=[['name', 'regexp']], fields={ 'address': KeyInfo(), 'cname': KeyInfo(), @@ -1365,8 +1384,9 @@ PATHS = { 'forward-to': KeyInfo(), 'mx-exchange': KeyInfo(), 'mx-preference': KeyInfo(), - 'name': KeyInfo(required=True), + 'name': KeyInfo(), 'ns': KeyInfo(), + 'regexp': KeyInfo(), 'srv-port': KeyInfo(), 'srv-priority': KeyInfo(), 'srv-target': KeyInfo(), diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d03a860..9501331 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -465,6 +465,24 @@ def polish_entry(entry, path_info, module, for_text): for key, field_info in path_info.fields.items(): if field_info.required and key not in entry: module.fail_json(msg='Key "{key}" must be present{for_text}.'.format(key=key, for_text=for_text)) + for require_list in path_info.required_one_of: + found_req_keys = [rk for rk in require_list if rk in entry] + if len(require_list) > 0 and not found_req_keys: + module.fail_json( + msg='Every element in data must contain one of {required_keys}. For example, the element{for_text} does not provide it.'.format( + required_keys=', '.join(['"{k}"'.format(k=k) for k in require_list]), + for_text=for_text, + ) + ) + for exclusive_list in path_info.mutually_exclusive: + found_ex_keys = [ek for ek in exclusive_list if ek in entry] + if len(found_ex_keys) > 1: + module.fail_json( + msg='Keys {exclusive_keys} cannot be used at the same time{for_text}.'.format( + exclusive_keys=', '.join(['"{k}"'.format(k=k) for k in found_ex_keys]), + for_text=for_text, + ) + ) def remove_irrelevant_data(entry, path_info): diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 6220e29..941a0c2 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -54,6 +54,22 @@ def test_api_data_errors(): APIData(stratify_keys=['foo'], fields={}) assert exc.value.args[0] == 'Stratify key foo must be in fields!' + with pytest.raises(ValueError) as exc: + APIData(required_one_of=['foo'], fields={}) + assert exc.value.args[0] == 'Require one of element at index #1 must be a list!' + + with pytest.raises(ValueError) as exc: + APIData(required_one_of=[['foo']], fields={}) + assert exc.value.args[0] == 'Require one of key foo must be in fields!' + + with pytest.raises(ValueError) as exc: + APIData(mutually_exclusive=['foo'], fields={}) + assert exc.value.args[0] == 'Mutually exclusive element at index #1 must be a list!' + + with pytest.raises(ValueError) as exc: + APIData(mutually_exclusive=[['foo']], fields={}) + assert exc.value.args[0] == 'Mutually exclusive key foo must be in fields!' + def test_key_info_errors(): values = [ diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index 2c6e0bd..f303ccf 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -385,9 +385,9 @@ class TestRouterosApiModifyModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: args = self.config_module_args.copy() args.update({ - 'path': 'ip dns static', + 'path': 'ip dhcp-server', 'data': [{ - 'address': '1.2.3.4', + 'interface': 'eth0', }], }) set_module_args(args) @@ -397,6 +397,40 @@ class TestRouterosApiModifyModule(ModuleTestCase): self.assertEqual(result['failed'], True) self.assertEqual(result['msg'], 'Every element in data must contain "name". For example, the element at index #1 does not provide it.') + def test_invalid_required_one_of_missing(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'address': '192.168.88.1', + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Every element in data must contain one of "name", "regexp". For example, the element at index 1 does not provide it.') + + def test_invalid_mutually_exclusive_both(self): + with self.assertRaises(AnsibleFailJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dns static', + 'data': [{ + 'name': 'foo', + 'regexp': 'bar', + 'address': '192.168.88.1', + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['failed'], True) + self.assertEqual(result['msg'], 'Keys "name", "regexp" cannot be used at the same time at index 1.') + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', new=create_fake_path(('ip', 'dns', 'static'), START_IP_DNS_STATIC, read_only=True)) def test_sync_list_idempotent(self): From 709abfb13fbc807b7e2b97eef7f9dd3f7ae41d9d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 Dec 2022 08:52:49 +0100 Subject: [PATCH 104/365] Prepare 2.6.0 release. --- changelogs/fragments/2.6.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.6.0.yml diff --git a/changelogs/fragments/2.6.0.yml b/changelogs/fragments/2.6.0.yml new file mode 100644 index 0000000..4b1469c --- /dev/null +++ b/changelogs/fragments/2.6.0.yml @@ -0,0 +1 @@ +release_summary: Regular bugfix and feature release. diff --git a/galaxy.yml b/galaxy.yml index c9547fa..f473b7e 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.5.0 +version: 2.6.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From d2caf56215ab6e0ab0c17cba843b71735ebeb4cc Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 1 Jan 2023 08:14:34 +0100 Subject: [PATCH 105/365] Release 2.6.0. --- CHANGELOG.rst | 20 ++++++++++++++++++++ changelogs/changelog.yaml | 16 ++++++++++++++++ changelogs/fragments/142-dns-regexp.yml | 6 ------ changelogs/fragments/143-add-wireguard.yml | 2 -- changelogs/fragments/2.6.0.yml | 1 - 5 files changed, 36 insertions(+), 9 deletions(-) delete mode 100644 changelogs/fragments/142-dns-regexp.yml delete mode 100644 changelogs/fragments/143-add-wireguard.yml delete mode 100644 changelogs/fragments/2.6.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7fc8d04..0a344ea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,26 @@ Community RouterOS Release Notes .. contents:: Topics +v2.6.0 +====== + +Release Summary +--------------- + +Regular bugfix and feature release. + +Minor Changes +------------- + +- api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). +- api_modify, api_info - support API paths ``interface wireguard``, ``interface wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). + +Bugfixes +-------- + +- api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). +- api_modify, api_info - do not crash if router contains ``regexp`` DNS entries in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + v2.5.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 76493f3..8b3448c 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -368,3 +368,19 @@ releases: - 137-api.yml - 2.5.0.yml release_date: '2022-12-04' + 2.6.0: + changes: + bugfixes: + - api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify, api_info - do not crash if router contains ``regexp`` DNS entries + in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + minor_changes: + - api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify, api_info - support API paths ``interface wireguard``, ``interface + wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). + release_summary: Regular bugfix and feature release. + fragments: + - 142-dns-regexp.yml + - 143-add-wireguard.yml + - 2.6.0.yml + release_date: '2023-01-01' diff --git a/changelogs/fragments/142-dns-regexp.yml b/changelogs/fragments/142-dns-regexp.yml deleted file mode 100644 index b7538ac..0000000 --- a/changelogs/fragments/142-dns-regexp.yml +++ /dev/null @@ -1,6 +0,0 @@ -minor_changes: - - api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). - -bugfixes: - - api_modify, api_info - do not crash if router contains ``regexp`` DNS entries in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). - - api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). diff --git a/changelogs/fragments/143-add-wireguard.yml b/changelogs/fragments/143-add-wireguard.yml deleted file mode 100644 index a098092..0000000 --- a/changelogs/fragments/143-add-wireguard.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``interface wireguard``, ``interface wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). diff --git a/changelogs/fragments/2.6.0.yml b/changelogs/fragments/2.6.0.yml deleted file mode 100644 index 4b1469c..0000000 --- a/changelogs/fragments/2.6.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Regular bugfix and feature release. From f38b01d7bbc19e1c0fd2a8c90d948f34e5e1e9ba Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Sun, 1 Jan 2023 22:18:24 +0100 Subject: [PATCH 106/365] API update (#144) * API update Signed-off-by: Tomas Herfert * fix changelog fragment directory Signed-off-by: Tomas Herfert Signed-off-by: Tomas Herfert Co-authored-by: Tomas Herfert --- changelogs/fragments/144-paths.yml | 4 + plugins/module_utils/_api_data.py | 128 ++++++++++++++++++++++++++++- plugins/modules/api_info.py | 3 + plugins/modules/api_modify.py | 3 + 4 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/144-paths.yml diff --git a/changelogs/fragments/144-paths.yml b/changelogs/fragments/144-paths.yml new file mode 100644 index 0000000..6ab6653 --- /dev/null +++ b/changelogs/fragments/144-paths.yml @@ -0,0 +1,4 @@ +minor_changes: + - api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). +bugfixes: + - api_modify, api_info - defaults corrected for fields in ``interface wireguard peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 038ddef..aec6640 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1184,14 +1184,14 @@ PATHS = { fully_understood=True, primary_keys=('public-key', 'interface'), fields={ - 'allowed-address': KeyInfo(), + 'allowed-address': KeyInfo(required=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), - 'endpoint-address': KeyInfo(), + 'endpoint-address': KeyInfo(default=''), 'endpoint-port': KeyInfo(default=0), 'interface': KeyInfo(), - 'persistent-keepalive': KeyInfo(), - 'preshared-key': KeyInfo(), + 'persistent-keepalive': KeyInfo(can_disable=True, remove_value=0), + 'preshared-key': KeyInfo(can_disable=True, remove_value=''), 'public-key': KeyInfo(), }, ), @@ -1279,6 +1279,17 @@ PATHS = { 'network': KeyInfo(automatically_computed_from=('address', )), }, ), + ('ip', 'arp'): APIData( + fully_understood=True, + fields={ + 'address': KeyInfo(default='0.0.0.0'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'mac-address': KeyInfo(default='00:00:00:00:00:00'), + 'published': KeyInfo(default=False), + }, + ), ('ip', 'cloud'): APIData( single_value=True, fully_understood=True, @@ -1616,6 +1627,62 @@ PATHS = { 'ttl': KeyInfo(can_disable=True), }, ), + ('ip', 'firewall', 'raw'): APIData( + fully_understood=True, + stratify_keys=('chain',), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ('ip', 'hotspot', 'user'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -1973,6 +2040,59 @@ PATHS = { 'tls-host': KeyInfo(can_disable=True), } ), + ('ipv6', 'firewall', 'raw'): APIData( + fully_understood=True, + stratify_keys=('chain',), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + } + ), ('ipv6', 'nd'): APIData( fully_understood=True, primary_keys=('interface', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 9d94088..276033d 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -84,6 +84,7 @@ options: - ip accounting - ip accounting web-access - ip address + - ip arp - ip cloud - ip cloud advanced - ip dhcp-client @@ -99,6 +100,7 @@ options: - ip firewall filter - ip firewall mangle - ip firewall nat + - ip firewall raw - ip firewall service-port - ip hotspot service-port - ip ipsec identity @@ -128,6 +130,7 @@ options: - ipv6 firewall address-list - ipv6 firewall filter - ipv6 firewall mangle + - ipv6 firewall raw - ipv6 nd - ipv6 nd prefix default - ipv6 route diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 9501331..39f7fcf 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -89,6 +89,7 @@ options: - ip accounting - ip accounting web-access - ip address + - ip arp - ip cloud - ip cloud advanced - ip dhcp-client @@ -104,6 +105,7 @@ options: - ip firewall filter - ip firewall mangle - ip firewall nat + - ip firewall raw - ip firewall service-port - ip hotspot service-port - ip ipsec identity @@ -133,6 +135,7 @@ options: - ipv6 firewall address-list - ipv6 firewall filter - ipv6 firewall mangle + - ipv6 firewall raw - ipv6 nd - ipv6 nd prefix default - ipv6 route From 7166a0b35c0f207c5d0191d40f5d80c1454d6ea8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 14 Jan 2023 14:12:35 +0100 Subject: [PATCH 107/365] Prepare 2.7.0 release. --- changelogs/fragments/2.7.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.7.0.yml diff --git a/changelogs/fragments/2.7.0.yml b/changelogs/fragments/2.7.0.yml new file mode 100644 index 0000000..754fee6 --- /dev/null +++ b/changelogs/fragments/2.7.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index f473b7e..1118e2c 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.6.0 +version: 2.7.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From e7dafebc7ab3bea0ed68e602b250bc54824c5395 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 14 Jan 2023 15:15:46 +0100 Subject: [PATCH 108/365] Release 2.7.0. --- CHANGELOG.rst | 18 ++++++++++++++++++ changelogs/changelog.yaml | 13 +++++++++++++ changelogs/fragments/144-paths.yml | 4 ---- changelogs/fragments/2.7.0.yml | 1 - 4 files changed, 31 insertions(+), 5 deletions(-) delete mode 100644 changelogs/fragments/144-paths.yml delete mode 100644 changelogs/fragments/2.7.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0a344ea..31a28c0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,24 @@ Community RouterOS Release Notes .. contents:: Topics +v2.7.0 +====== + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). + +Bugfixes +-------- + +- api_modify, api_info - defaults corrected for fields in ``interface wireguard peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). + v2.6.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 8b3448c..ad9c9f8 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -384,3 +384,16 @@ releases: - 143-add-wireguard.yml - 2.6.0.yml release_date: '2023-01-01' + 2.7.0: + changes: + bugfixes: + - api_modify, api_info - defaults corrected for fields in ``interface wireguard + peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). + minor_changes: + - api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, + ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). + release_summary: Bugfix and feature release. + fragments: + - 144-paths.yml + - 2.7.0.yml + release_date: '2023-01-14' diff --git a/changelogs/fragments/144-paths.yml b/changelogs/fragments/144-paths.yml deleted file mode 100644 index 6ab6653..0000000 --- a/changelogs/fragments/144-paths.yml +++ /dev/null @@ -1,4 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). -bugfixes: - - api_modify, api_info - defaults corrected for fields in ``interface wireguard peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). diff --git a/changelogs/fragments/2.7.0.yml b/changelogs/fragments/2.7.0.yml deleted file mode 100644 index 754fee6..0000000 --- a/changelogs/fragments/2.7.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. \ No newline at end of file From 622680fe3f35c052f1d92c497bfc2f45de15eb52 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 6 Feb 2023 07:42:39 +0100 Subject: [PATCH 109/365] Remove unneccessary imports (#149) * Remove unneccessary imports. * Add noqas. --- changelogs/fragments/remove-unneeded-imports.yml | 2 ++ plugins/cliconf/routeros.py | 7 ++----- plugins/module_utils/api.py | 3 +-- plugins/modules/api.py | 3 --- plugins/modules/api_facts.py | 1 - plugins/modules/command.py | 2 -- plugins/terminal/routeros.py | 2 -- 7 files changed, 5 insertions(+), 15 deletions(-) create mode 100644 changelogs/fragments/remove-unneeded-imports.yml diff --git a/changelogs/fragments/remove-unneeded-imports.yml b/changelogs/fragments/remove-unneeded-imports.yml new file mode 100644 index 0000000..320f914 --- /dev/null +++ b/changelogs/fragments/remove-unneeded-imports.yml @@ -0,0 +1,2 @@ +bugfixes: + - "various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149)." diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py index 6a5cb2c..412627b 100644 --- a/plugins/cliconf/routeros.py +++ b/plugins/cliconf/routeros.py @@ -18,11 +18,8 @@ description: import re import json -from itertools import chain - -from ansible.module_utils.common.text.converters import to_bytes, to_text -from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list -from ansible.plugins.cliconf import CliconfBase, enable_mode +from ansible.module_utils.common.text.converters import to_text +from ansible.plugins.cliconf import CliconfBase class Cliconf(CliconfBase): diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 6ffa1a5..5c598f3 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -12,14 +12,13 @@ __metaclass__ = type from ansible.module_utils.basic import missing_required_lib from ansible.module_utils.common.text.converters import to_native -import re import ssl import traceback LIB_IMP_ERR = None try: from librouteros import connect - from librouteros.exceptions import LibRouterosError + from librouteros.exceptions import LibRouterosError # noqa: F401, pylint: disable=unused-import HAS_LIB = True except Exception as e: HAS_LIB = False diff --git a/plugins/modules/api.py b/plugins/modules/api.py index dbf9d3d..f9c619f 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -265,7 +265,6 @@ message: ''' from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.basic import missing_required_lib from ansible.module_utils.common.text.converters import to_native from ansible_collections.community.routeros.plugins.module_utils.quoting import ( @@ -282,8 +281,6 @@ from ansible_collections.community.routeros.plugins.module_utils.api import ( ) import re -import ssl -import traceback try: from librouteros.exceptions import LibRouterosError diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 59de196..f297236 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -178,7 +178,6 @@ ansible_facts: returned: I(gather_subset) contains C(routing) type: dict """ -import re from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import iteritems diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 83cd776..8442602 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -133,13 +133,11 @@ failed_conditions: sample: ['...', '...'] """ -import re import time from ansible_collections.community.routeros.plugins.module_utils.routeros import run_commands from ansible_collections.community.routeros.plugins.module_utils.routeros import routeros_argument_spec from ansible.module_utils.basic import AnsibleModule -from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional from ansible.module_utils.six import string_types diff --git a/plugins/terminal/routeros.py b/plugins/terminal/routeros.py index 1d3fa6c..9d50fa2 100644 --- a/plugins/terminal/routeros.py +++ b/plugins/terminal/routeros.py @@ -5,11 +5,9 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json import re from ansible.errors import AnsibleConnectionFailure -from ansible.module_utils.common.text.converters import to_text, to_bytes from ansible.plugins.terminal import TerminalBase from ansible.utils.display import Display From 1dfa79c5ef87703ee4535ff29f1c038cfffe0c7c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 12 Feb 2023 21:17:22 +0100 Subject: [PATCH 110/365] Remove unnecessary test imports. (#150) --- tests/sanity/extra/update-docs.py | 1 - tests/unit/compat/builtins.py | 2 +- tests/unit/compat/mock.py | 4 ++-- tests/unit/compat/unittest.py | 4 ++-- tests/unit/plugins/module_utils/test__api_data.py | 2 -- tests/unit/plugins/modules/test_api.py | 3 --- tests/unit/plugins/modules/test_api_facts.py | 3 --- tests/unit/plugins/modules/test_api_find_and_modify.py | 4 ---- tests/unit/plugins/modules/test_api_info.py | 3 --- tests/unit/plugins/modules/test_api_modify.py | 4 ---- 10 files changed, 5 insertions(+), 25 deletions(-) diff --git a/tests/sanity/extra/update-docs.py b/tests/sanity/extra/update-docs.py index 139fd87..68e2edf 100644 --- a/tests/sanity/extra/update-docs.py +++ b/tests/sanity/extra/update-docs.py @@ -6,7 +6,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import os import sys import subprocess diff --git a/tests/unit/compat/builtins.py b/tests/unit/compat/builtins.py index b0cc618..d548601 100644 --- a/tests/unit/compat/builtins.py +++ b/tests/unit/compat/builtins.py @@ -13,7 +13,7 @@ __metaclass__ = type # One unittest needs to import builtins via __import__() so we need to have # the string that represents it try: - import __builtin__ + import __builtin__ # noqa: F401, pylint: disable=unused-import except ImportError: BUILTINS = 'builtins' else: diff --git a/tests/unit/compat/mock.py b/tests/unit/compat/mock.py index f8f565d..bdbea94 100644 --- a/tests/unit/compat/mock.py +++ b/tests/unit/compat/mock.py @@ -20,12 +20,12 @@ 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 * + from unittest.mock import * # noqa: F401, pylint: disable=unused-import except ImportError: # Python 2 # pylint: disable=wildcard-import,unused-wildcard-import try: - from mock import * + from mock import * # noqa: F401, pylint: disable=unused-import except ImportError: print('You need the mock library installed on python2.x to run tests') diff --git a/tests/unit/compat/unittest.py b/tests/unit/compat/unittest.py index 1872e58..d50bab8 100644 --- a/tests/unit/compat/unittest.py +++ b/tests/unit/compat/unittest.py @@ -18,8 +18,8 @@ import sys if sys.version_info < (2, 7): try: # Need unittest2 on python2.6 - from unittest2 import * + from unittest2 import * # noqa: F401, pylint: disable=unused-import except ImportError: print('You need unittest2 installed on python2.6.x to run tests') else: - from unittest import * + from unittest import * # noqa: F401, pylint: disable=unused-import diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 941a0c2..1250fda 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -9,8 +9,6 @@ __metaclass__ = type import pytest -from ansible.module_utils.common.text.converters import to_native - from ansible_collections.community.routeros.plugins.module_utils._api_data import ( APIData, KeyInfo, diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index be63393..4cfdeef 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -6,9 +6,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json -import pytest - from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, Or, fake_ros_api from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py index 8c34be2..64985f8 100644 --- a/tests/unit/plugins/modules/test_api_facts.py +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -6,9 +6,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json -import pytest - from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index e1b1645..384bc88 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -6,15 +6,11 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json -import pytest - from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, ) from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase -from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS from ansible_collections.community.routeros.plugins.modules import api_find_and_modify diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index ac374dd..2dabc36 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -6,9 +6,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json -import pytest - from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index f303ccf..d70cf1f 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -6,15 +6,11 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import json -import pytest - from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, ) from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase -from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS from ansible_collections.community.routeros.plugins.modules import api_modify From d39b3522abecbb111505b205a5c58c8d22023056 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 12 Feb 2023 21:22:30 +0100 Subject: [PATCH 111/365] Remove unnecessary import. --- update-docs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/update-docs.py b/update-docs.py index 6f4fef8..17a431b 100755 --- a/update-docs.py +++ b/update-docs.py @@ -9,8 +9,6 @@ Updates DOCUMENTATION of modules using module_utils._api_data with the correct list of supported paths. ''' -import os - from plugins.module_utils._api_data import ( PATHS, join_path, From bbf5be5d71d90327f67e425de8d268f56ba02824 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 15 Feb 2023 22:28:50 +0100 Subject: [PATCH 112/365] Normalize bools in documentation. (#151) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fb7ad63..7378c34 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Example playbook: --- - name: RouterOS test with API hosts: localhost - gather_facts: no + gather_facts: false vars: hostname: 192.168.1.1 username: admin From ab87a27018a3f94b7ffbbb68f8c10f894e34edab Mon Sep 17 00:00:00 2001 From: phox142 Date: Mon, 27 Feb 2023 22:37:00 +0100 Subject: [PATCH 113/365] Add support for "ip firewall layer7-protocol" (#153) * Add support for "ip firewall layer7-protocol" * Add changelog fragment * Add changelog fragment --- changelogs/fragments/153-ip_firewall_layer7-protocol.yml | 2 ++ plugins/module_utils/_api_data.py | 9 +++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 13 insertions(+) create mode 100644 changelogs/fragments/153-ip_firewall_layer7-protocol.yml diff --git a/changelogs/fragments/153-ip_firewall_layer7-protocol.yml b/changelogs/fragments/153-ip_firewall_layer7-protocol.yml new file mode 100644 index 0000000..694c7ea --- /dev/null +++ b/changelogs/fragments/153-ip_firewall_layer7-protocol.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index aec6640..ec5ae3b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2759,6 +2759,15 @@ PATHS = { 'sip-timeout': KeyInfo(), }, ), + ('ip', 'firewall', 'layer7-protocol'): APIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'name': KeyInfo(), + 'regexp': KeyInfo(), + }, + ), ('ip', 'hotspot', 'service-port'): APIData( fixed_entries=True, primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 276033d..b5c684c 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -102,6 +102,7 @@ options: - ip firewall nat - ip firewall raw - ip firewall service-port + - ip firewall layer7-protocol - ip hotspot service-port - ip ipsec identity - ip ipsec peer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 39f7fcf..40d9069 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -107,6 +107,7 @@ options: - ip firewall nat - ip firewall raw - ip firewall service-port + - ip firewall layer7-protocol - ip hotspot service-port - ip ipsec identity - ip ipsec peer From 4d86ba1a7da1bf465d8a0397437d0f2b8c2defc0 Mon Sep 17 00:00:00 2001 From: phox142 Date: Fri, 10 Mar 2023 07:01:26 +0100 Subject: [PATCH 114/365] Correction and Bugfix for ip dhcp-server network (#156) * API_DATA > ('ip', 'dhcp-server', 'network') > netmask replace "automatically_computed_from" by 'can_disable=True, remove_value=0' automatically_computed_from does not seem to be used at any place in the code without 'can_disable=True, remove_value=0' task is marked as changed at each execution. * API_DATA > ('ip', 'dhcp-server', 'network') > next-server replace "default=''" by 'can_disable=True' The default in routeros is "no value" and it was not possible to remove a configured next-server * API_DATA > ('ip', 'dhcp-server', 'network') > gateway replace "automatically_computed_from" by "default=''" automatically_computed_from does not seem to be used * API_DATA > ('ip', 'dhcp-server', 'network') > dns-none replace "default=''" by "default=False" * Add changelogs fragment * Update changelogs/fragments/156-ip_dhcp-server_network.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/156-ip_dhcp-server_network.yml | 2 ++ plugins/module_utils/_api_data.py | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/156-ip_dhcp-server_network.yml diff --git a/changelogs/fragments/156-ip_dhcp-server_network.yml b/changelogs/fragments/156-ip_dhcp-server_network.yml new file mode 100644 index 0000000..d89f834 --- /dev/null +++ b/changelogs/fragments/156-ip_dhcp-server_network.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ec5ae3b..caec1ed 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1356,12 +1356,12 @@ PATHS = { 'comment': KeyInfo(can_disable=True, remove_value=''), 'dhcp-option': KeyInfo(default=''), 'dhcp-option-set': KeyInfo(default=''), - 'dns-none': KeyInfo(default=''), + 'dns-none': KeyInfo(default=False), 'dns-server': KeyInfo(default=''), 'domain': KeyInfo(default=''), - 'gateway': KeyInfo(automatically_computed_from=('address', )), - 'netmask': KeyInfo(automatically_computed_from=('address', )), - 'next-server': KeyInfo(default=''), + 'gateway': KeyInfo(default=''), + 'netmask': KeyInfo(can_disable=True, remove_value=0), + 'next-server': KeyInfo(can_disable=True), 'ntp-server': KeyInfo(default=''), 'wins-server': KeyInfo(default=''), }, From 720debb32357b174a73e668855a7e7d05477387a Mon Sep 17 00:00:00 2001 From: phox142 Date: Sat, 11 Mar 2023 18:16:43 +0100 Subject: [PATCH 115/365] Add support to disable ipv6 in API paths ``ipv6 settings`` (#158) * add support to disable ipv6 * Add changelogs fragment * Update changelogs/fragments/158-ipv6_settings-disable.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/158-ipv6_settings-disable.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/158-ipv6_settings-disable.yml diff --git a/changelogs/fragments/158-ipv6_settings-disable.yml b/changelogs/fragments/158-ipv6_settings-disable.yml new file mode 100644 index 0000000..11e2c3e --- /dev/null +++ b/changelogs/fragments/158-ipv6_settings-disable.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/158). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index caec1ed..75a3610 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1086,6 +1086,7 @@ PATHS = { fields={ 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), + 'disable-ipv6': KeyInfo(default=False), 'forward': KeyInfo(default=True), 'max-neighbor-entries': KeyInfo(default=8192), }, From 071f742100bf9f9ef413261a6c48e2f544bbef56 Mon Sep 17 00:00:00 2001 From: phox142 Date: Sat, 11 Mar 2023 18:17:26 +0100 Subject: [PATCH 116/365] Adapt SNMP support (#159) * snmp support * Add changelog fragment * Update changelogs/fragments/159-snmp_community.yml Co-authored-by: Felix Fontein * Update changelogs/fragments/159-snmp_community.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/159-snmp_community.yml | 3 +++ plugins/module_utils/_api_data.py | 27 +++++++++++---------- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 changelogs/fragments/159-snmp_community.yml diff --git a/changelogs/fragments/159-snmp_community.yml b/changelogs/fragments/159-snmp_community.yml new file mode 100644 index 0000000..b8d678e --- /dev/null +++ b/changelogs/fragments/159-snmp_community.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). + - api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 75a3610..8d78588 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -748,20 +748,20 @@ PATHS = { }, ), ('snmp', 'community'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'addresses': KeyInfo(), - 'authentication-password': KeyInfo(), - 'authentication-protocol': KeyInfo(), - 'disabled': KeyInfo(), - 'encryption-password': KeyInfo(), - 'encryption-protocol': KeyInfo(), - 'name': KeyInfo(), - 'read-access': KeyInfo(), - 'security': KeyInfo(), - 'write-access': KeyInfo(), + 'addresses': KeyInfo(default='::/0'), + 'authentication-password': KeyInfo(default=''), + 'authentication-protocol': KeyInfo(default='MD5'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'encryption-password': KeyInfo(default=''), + 'encryption-protocol': KeyInfo(default='DES'), + 'name': KeyInfo(required=True), + 'read-access': KeyInfo(default=True), + 'security': KeyInfo(default='none'), + 'write-access': KeyInfo(default=False), }, ), ('caps-man', 'aaa'): APIData( @@ -2286,6 +2286,7 @@ PATHS = { 'trap-generators': KeyInfo(default='temp-exception'), 'trap-target': KeyInfo(default=''), 'trap-version': KeyInfo(default=1), + 'trap-interfaces': KeyInfo(default=''), }, ), ('system', 'clock'): APIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index b5c684c..3220a52 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -154,6 +154,7 @@ options: - routing rip - routing ripng - snmp + - snmp community - system clock - system clock manual - system identity diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 40d9069..029fcd0 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -159,6 +159,7 @@ options: - routing rip - routing ripng - snmp + - snmp community - system clock - system clock manual - system identity From 432992847423e91432a278c8e0c9098bf47d5f9b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 19 Mar 2023 13:14:55 +0100 Subject: [PATCH 117/365] ip dhcp-client: dhcp-options can be removed with value '' (#154) * dhcp-options can be removed with value ''. * Fix handling of disabled keys on creation. * Fix typo. --- .../154-ip-dhcp-client-dhcp-options.yml | 3 + plugins/module_utils/_api_data.py | 2 +- plugins/modules/api_modify.py | 20 ++- tests/unit/plugins/modules/fake_api.py | 6 +- tests/unit/plugins/modules/test_api_modify.py | 146 +++++++++++++++++- 5 files changed, 166 insertions(+), 11 deletions(-) create mode 100644 changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml diff --git a/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml b/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml new file mode 100644 index 0000000..016eb15 --- /dev/null +++ b/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml @@ -0,0 +1,3 @@ +bugfixes: + - "api_info, api_modify - fix default and remove behavior for ``dhcp-options`` in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, https://github.com/ansible-collections/community.routeros/pull/154)." + - "api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 8d78588..0d3e82f 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1314,7 +1314,7 @@ PATHS = { 'add-default-route': KeyInfo(default=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'default-route-distance': KeyInfo(default=1), - 'dhcp-options': KeyInfo(default='hostname,clientid'), + 'dhcp-options': KeyInfo(default='hostname,clientid', can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'interface': KeyInfo(), 'script': KeyInfo(can_disable=True), diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 029fcd0..0bf2c71 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -542,6 +542,22 @@ def get_api_data(api_path, path_info): return entries +def prepare_for_add(entry, path_info): + new_entry = {} + for k, v in entry.items(): + if k.startswith('!'): + real_k = k[1:] + remove_value = path_info.fields[real_k].remove_value + if remove_value is not None: + k = real_k + v = remove_value + else: + if v is None: + v = path_info.fields[k].remove_value + new_entry[k] = v + return new_entry + + def sync_list(module, api, path, path_info): handle_absent_entries = module.params['handle_absent_entries'] handle_entries_content = module.params['handle_entries_content'] @@ -661,7 +677,7 @@ def sync_list(module, api, path, path_info): ) for entry in create_list: try: - entry['.id'] = api_path.add(**entry) + entry['.id'] = api_path.add(**prepare_for_add(entry, path_info)) except (LibRouterosError, UnicodeEncodeError) as e: module.fail_json( msg='Error while creating entry: {error}'.format( @@ -850,7 +866,7 @@ def sync_with_primary_keys(module, api, path, path_info): ) for entry in create_list: try: - entry['.id'] = api_path.add(**entry) + entry['.id'] = api_path.add(**prepare_for_add(entry, path_info)) # Store ID for primary keys pks = tuple(entry[primary_key] for primary_key in primary_keys) id_by_key[pks] = entry['.id'] diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index 37fae3b..a5ddb31 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -118,9 +118,9 @@ class Or(object): return repr(self.args) -def _normalize_entry(entry, path_info): +def _normalize_entry(entry, path_info, on_create=False): for key, data in path_info.fields.items(): - if key not in entry and data.default is not None and not data.can_disable: + if key not in entry and data.default is not None and (not data.can_disable or on_create): entry[key] = data.default if data.can_disable: if key in entry and entry[key] in (None, data.remove_value): @@ -188,7 +188,7 @@ class Path(object): '.id': id, } entry.update(kwargs) - _normalize_entry(entry, self._path_info) + _normalize_entry(entry, self._path_info, on_create=True) self._values.append(entry) return id diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index d70cf1f..7897973 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -89,7 +89,48 @@ START_IP_ADDRESS = [ START_IP_ADDRESS_OLD_DATA = massage_expected_result_data(START_IP_ADDRESS, ('ip', 'address')) -START_IP_DHCP_SEVER_LEASE = [ +START_IP_DHCP_CLIENT = [ + { + "!comment": None, + "!script": None, + ".id": "*1", + "add-default-route": True, + "default-route-distance": 1, + "dhcp-options": "hostname,clientid", + "disabled": False, + "interface": "ether1", + "use-peer-dns": True, + "use-peer-ntp": True, + }, + { + "!comment": None, + "!dhcp-options": None, + "!script": None, + ".id": "*2", + "add-default-route": True, + "default-route-distance": 1, + "disabled": False, + "interface": "ether2", + "use-peer-dns": True, + "use-peer-ntp": True, + }, + { + "!comment": None, + "!script": None, + ".id": "*3", + "add-default-route": True, + "default-route-distance": 1, + "dhcp-options": "hostname", + "disabled": False, + "interface": "ether3", + "use-peer-dns": True, + "use-peer-ntp": True, + }, +] + +START_IP_DHCP_CLIENT_OLD_DATA = massage_expected_result_data(START_IP_DHCP_CLIENT, ('ip', 'dhcp-client')) + +START_IP_DHCP_SERVER_LEASE = [ { '.id': '*1', 'address': '192.168.88.2', @@ -155,7 +196,7 @@ START_IP_DHCP_SEVER_LEASE = [ }, ] -START_IP_DHCP_SEVER_LEASE_OLD_DATA = massage_expected_result_data(START_IP_DHCP_SEVER_LEASE, ('ip', 'dhcp-server', 'lease')) +START_IP_DHCP_SERVER_LEASE_OLD_DATA = massage_expected_result_data(START_IP_DHCP_SERVER_LEASE, ('ip', 'dhcp-server', 'lease')) START_INTERFACE_LIST = [ { @@ -1729,7 +1770,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): ]) @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', - new=create_fake_path(('ip', 'dhcp-server', 'lease'), START_IP_DHCP_SEVER_LEASE, read_only=True)) + new=create_fake_path(('ip', 'dhcp-server', 'lease'), START_IP_DHCP_SERVER_LEASE, read_only=True)) def test_absent_value(self): with self.assertRaises(AnsibleExitJson) as exc: args = self.config_module_args.copy() @@ -1769,8 +1810,103 @@ class TestRouterosApiModifyModule(ModuleTestCase): result = exc.exception.args[0] self.assertEqual(result['changed'], False) - self.assertEqual(result['old_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) - self.assertEqual(result['new_data'], START_IP_DHCP_SEVER_LEASE_OLD_DATA) + self.assertEqual(result['old_data'], START_IP_DHCP_SERVER_LEASE_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DHCP_SERVER_LEASE_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dhcp-client'), START_IP_DHCP_CLIENT, read_only=True)) + def test_default_remove_combination_idempotent(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dhcp-client', + 'data': [ + { + 'interface': 'ether1', + }, + { + 'interface': 'ether2', + 'dhcp-options': None, + }, + { + 'interface': 'ether3', + 'dhcp-options': 'hostname', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], START_IP_DHCP_CLIENT_OLD_DATA) + self.assertEqual(result['new_data'], START_IP_DHCP_CLIENT_OLD_DATA) + + @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', + new=create_fake_path(('ip', 'dhcp-client'), [])) + def test_default_remove_combination_create(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip dhcp-client', + 'data': [ + { + 'interface': 'ether1', + }, + { + 'interface': 'ether2', + 'dhcp-options': None, + }, + { + 'interface': 'ether3', + 'dhcp-options': 'hostname', + }, + ], + 'handle_absent_entries': 'remove', + 'handle_entries_content': 'remove', + 'ensure_order': True, + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], True) + self.assertEqual(result['old_data'], []) + self.assertEqual(result['new_data'], [ + { + ".id": "*NEW1", + "add-default-route": True, + "default-route-distance": 1, + "dhcp-options": "hostname,clientid", + "disabled": False, + "interface": "ether1", + "use-peer-dns": True, + "use-peer-ntp": True, + }, + { + # "!dhcp-options": None, + ".id": "*NEW2", + "add-default-route": True, + "default-route-distance": 1, + "disabled": False, + "interface": "ether2", + "use-peer-dns": True, + "use-peer-ntp": True, + }, + { + ".id": "*NEW3", + "add-default-route": True, + "default-route-distance": 1, + "dhcp-options": "hostname", + "disabled": False, + "interface": "ether3", + "use-peer-dns": True, + "use-peer-ntp": True, + }, + ]) @patch('ansible_collections.community.routeros.plugins.modules.api_modify.compose_api_path', new=create_fake_path(('interface', 'list'), START_INTERFACE_LIST, read_only=True)) From c1a6ae86587d292a01920494f7a2547ef6e2c5e6 Mon Sep 17 00:00:00 2001 From: Sam Grimee - LX2SG Date: Thu, 23 Mar 2023 21:25:23 +0100 Subject: [PATCH 118/365] Workaround prompt issues between ROS 6.49 and 7.1.5 (#62) (#161) * Prompt support for ROS 6.49+ (#62) * More precise version match (#62) * Add changelog fragment and lint (#62) * Update changelogs/fragments/161-workaround-prompt-with-space.yml Co-authored-by: Felix Fontein * Vendor version package to support older ansible versions (#62) * Update plugins/module_utils/routeros.py Co-authored-by: Felix Fontein * Update plugins/module_utils/routeros.py Co-authored-by: Felix Fontein * move PSF-2.0.txt to LICENSES folder --------- Co-authored-by: Felix Fontein --- LICENSES/PSF-2.0.txt | 48 +++ .../161-workaround-prompt-with-space.yml | 3 + plugins/module_utils/_version.py | 345 ++++++++++++++++++ plugins/module_utils/routeros.py | 14 + plugins/module_utils/version.py | 18 + 5 files changed, 428 insertions(+) create mode 100644 LICENSES/PSF-2.0.txt create mode 100644 changelogs/fragments/161-workaround-prompt-with-space.yml create mode 100644 plugins/module_utils/_version.py create mode 100644 plugins/module_utils/version.py diff --git a/LICENSES/PSF-2.0.txt b/LICENSES/PSF-2.0.txt new file mode 100644 index 0000000..35acd7f --- /dev/null +++ b/LICENSES/PSF-2.0.txt @@ -0,0 +1,48 @@ +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/changelogs/fragments/161-workaround-prompt-with-space.yml b/changelogs/fragments/161-workaround-prompt-with-space.yml new file mode 100644 index 0000000..beafb31 --- /dev/null +++ b/changelogs/fragments/161-workaround-prompt-with-space.yml @@ -0,0 +1,3 @@ +minor_changes: + - command - workaround for extra characters in stdout in RouterOS versions between 6.49 and 7.1.5 + (https://github.com/ansible-collections/community.routeros/issues/62, https://github.com/ansible-collections/community.routeros/pull/161). diff --git a/plugins/module_utils/_version.py b/plugins/module_utils/_version.py new file mode 100644 index 0000000..f795407 --- /dev/null +++ b/plugins/module_utils/_version.py @@ -0,0 +1,345 @@ +# Vendored copy of distutils/version.py from CPython 3.9.5 +# +# Implements multiple version numbering conventions for the +# Python Module Distribution Utilities. +# +# Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. +# PSF License (see LICENSES/PSF-2.0.txt or https://opensource.org/licenses/Python-2.0) +# SPDX-License-Identifier: PSF-2.0 +# + +"""Provides classes to represent module version numbers (one class for +each style of version numbering). There are currently two such classes +implemented: StrictVersion and LooseVersion. + +Every version number class implements the following interface: + * the 'parse' method takes a string and parses it to some internal + representation; if the string is an invalid version number, + 'parse' raises a ValueError exception + * the class constructor takes an optional string argument which, + if supplied, is passed to 'parse' + * __str__ reconstructs the string that was passed to 'parse' (or + an equivalent string -- ie. one that will generate an equivalent + version number instance) + * __repr__ generates Python code to recreate the version number instance + * _cmp compares the current instance with either another instance + of the same class or a string (which will be parsed to an instance + of the same class, thus must follow the same rules) +""" + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re + +try: + RE_FLAGS = re.VERBOSE | re.ASCII +except AttributeError: + RE_FLAGS = re.VERBOSE + + +class Version: + """Abstract base class for version numbering classes. Just provides + constructor (__init__) and reproducer (__repr__), because those + seem to be the same for all version numbering classes; and route + rich comparisons to _cmp. + """ + + def __init__(self, vstring=None): + if vstring: + self.parse(vstring) + + def __repr__(self): + return "%s ('%s')" % (self.__class__.__name__, str(self)) + + def __eq__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c == 0 + + def __lt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c < 0 + + def __le__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c <= 0 + + def __gt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c > 0 + + def __ge__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c >= 0 + + +# Interface for version-number classes -- must be implemented +# by the following classes (the concrete ones -- Version should +# be treated as an abstract class). +# __init__ (string) - create and take same action as 'parse' +# (string parameter is optional) +# parse (string) - convert a string representation to whatever +# internal representation is appropriate for +# this style of version numbering +# __str__ (self) - convert back to a string; should be very similar +# (if not identical to) the string supplied to parse +# __repr__ (self) - generate Python code to recreate +# the instance +# _cmp (self, other) - compare two version numbers ('other' may +# be an unparsed version string, or another +# instance of your version class) + + +class StrictVersion(Version): + """Version numbering for anal retentives and software idealists. + Implements the standard interface for version number classes as + described above. A version number consists of two or three + dot-separated numeric components, with an optional "pre-release" tag + on the end. The pre-release tag consists of the letter 'a' or 'b' + followed by a number. If the numeric components of two version + numbers are equal, then one with a pre-release tag will always + be deemed earlier (lesser) than one without. + + The following are valid version numbers (shown in the order that + would be obtained by sorting according to the supplied cmp function): + + 0.4 0.4.0 (these two are equivalent) + 0.4.1 + 0.5a1 + 0.5b3 + 0.5 + 0.9.6 + 1.0 + 1.0.4a3 + 1.0.4b1 + 1.0.4 + + The following are examples of invalid version numbers: + + 1 + 2.7.2.2 + 1.3.a4 + 1.3pl1 + 1.3c4 + + The rationale for this version numbering system will be explained + in the distutils documentation. + """ + + version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', + RE_FLAGS) + + def parse(self, vstring): + match = self.version_re.match(vstring) + if not match: + raise ValueError("invalid version number '%s'" % vstring) + + (major, minor, patch, prerelease, prerelease_num) = \ + match.group(1, 2, 4, 5, 6) + + if patch: + self.version = tuple(map(int, [major, minor, patch])) + else: + self.version = tuple(map(int, [major, minor])) + (0,) + + if prerelease: + self.prerelease = (prerelease[0], int(prerelease_num)) + else: + self.prerelease = None + + def __str__(self): + if self.version[2] == 0: + vstring = '.'.join(map(str, self.version[0:2])) + else: + vstring = '.'.join(map(str, self.version)) + + if self.prerelease: + vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) + + return vstring + + def _cmp(self, other): + if isinstance(other, str): + other = StrictVersion(other) + elif not isinstance(other, StrictVersion): + return NotImplemented + + if self.version != other.version: + # numeric versions don't match + # prerelease stuff doesn't matter + if self.version < other.version: + return -1 + else: + return 1 + + # have to compare prerelease + # case 1: neither has prerelease; they're equal + # case 2: self has prerelease, other doesn't; other is greater + # case 3: self doesn't have prerelease, other does: self is greater + # case 4: both have prerelease: must compare them! + + if (not self.prerelease and not other.prerelease): + return 0 + elif (self.prerelease and not other.prerelease): + return -1 + elif (not self.prerelease and other.prerelease): + return 1 + elif (self.prerelease and other.prerelease): + if self.prerelease == other.prerelease: + return 0 + elif self.prerelease < other.prerelease: + return -1 + else: + return 1 + else: + raise AssertionError("never get here") + +# end class StrictVersion + +# The rules according to Greg Stein: +# 1) a version number has 1 or more numbers separated by a period or by +# sequences of letters. If only periods, then these are compared +# left-to-right to determine an ordering. +# 2) sequences of letters are part of the tuple for comparison and are +# compared lexicographically +# 3) recognize the numeric components may have leading zeroes +# +# The LooseVersion class below implements these rules: a version number +# string is split up into a tuple of integer and string components, and +# comparison is a simple tuple comparison. This means that version +# numbers behave in a predictable and obvious way, but a way that might +# not necessarily be how people *want* version numbers to behave. There +# wouldn't be a problem if people could stick to purely numeric version +# numbers: just split on period and compare the numbers as tuples. +# However, people insist on putting letters into their version numbers; +# the most common purpose seems to be: +# - indicating a "pre-release" version +# ('alpha', 'beta', 'a', 'b', 'pre', 'p') +# - indicating a post-release patch ('p', 'pl', 'patch') +# but of course this can't cover all version number schemes, and there's +# no way to know what a programmer means without asking him. +# +# The problem is what to do with letters (and other non-numeric +# characters) in a version number. The current implementation does the +# obvious and predictable thing: keep them as strings and compare +# lexically within a tuple comparison. This has the desired effect if +# an appended letter sequence implies something "post-release": +# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". +# +# However, if letters in a version number imply a pre-release version, +# the "obvious" thing isn't correct. Eg. you would expect that +# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison +# implemented here, this just isn't so. +# +# Two possible solutions come to mind. The first is to tie the +# comparison algorithm to a particular set of semantic rules, as has +# been done in the StrictVersion class above. This works great as long +# as everyone can go along with bondage and discipline. Hopefully a +# (large) subset of Python module programmers will agree that the +# particular flavour of bondage and discipline provided by StrictVersion +# provides enough benefit to be worth using, and will submit their +# version numbering scheme to its domination. The free-thinking +# anarchists in the lot will never give in, though, and something needs +# to be done to accommodate them. +# +# Perhaps a "moderately strict" version class could be implemented that +# lets almost anything slide (syntactically), and makes some heuristic +# assumptions about non-digits in version number strings. This could +# sink into special-case-hell, though; if I was as talented and +# idiosyncratic as Larry Wall, I'd go ahead and implement a class that +# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is +# just as happy dealing with things like "2g6" and "1.13++". I don't +# think I'm smart enough to do it right though. +# +# In any case, I've coded the test suite for this module (see +# ../test/test_version.py) specifically to fail on things like comparing +# "1.2a2" and "1.2". That's not because the *code* is doing anything +# wrong, it's because the simple, obvious design doesn't match my +# complicated, hairy expectations for real-world version numbers. It +# would be a snap to fix the test suite to say, "Yep, LooseVersion does +# the Right Thing" (ie. the code matches the conception). But I'd rather +# have a conception that matches common notions about version numbers. + + +class LooseVersion(Version): + """Version numbering for anarchists and software realists. + Implements the standard interface for version number classes as + described above. A version number consists of a series of numbers, + separated by either periods or strings of letters. When comparing + version numbers, the numeric components will be compared + numerically, and the alphabetic components lexically. The following + are all valid version numbers, in no particular order: + + 1.5.1 + 1.5.2b2 + 161 + 3.10a + 8.02 + 3.4j + 1996.07.12 + 3.2.pl0 + 3.1.1.6 + 2g6 + 11g + 0.960923 + 2.2beta29 + 1.13++ + 5.5.kw + 2.0b1pl0 + + In fact, there is no such thing as an invalid version number under + this scheme; the rules for comparison are simple and predictable, + but may not always give the results you want (for some definition + of "want"). + """ + + component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) + + def __init__(self, vstring=None): + if vstring: + self.parse(vstring) + + def parse(self, vstring): + # I've given up on thinking I can reconstruct the version string + # from the parsed tuple -- so I just store the string here for + # use by __str__ + self.vstring = vstring + components = [x for x in self.component_re.split(vstring) if x and x != '.'] + for i, obj in enumerate(components): + try: + components[i] = int(obj) + except ValueError: + pass + + self.version = components + + def __str__(self): + return self.vstring + + def __repr__(self): + return "LooseVersion ('%s')" % str(self) + + def _cmp(self, other): + if isinstance(other, str): + other = LooseVersion(other) + elif not isinstance(other, LooseVersion): + return NotImplemented + + if self.version == other.version: + return 0 + if self.version < other.version: + return -1 + if self.version > other.version: + return 1 + +# end class LooseVersion diff --git a/plugins/module_utils/routeros.py b/plugins/module_utils/routeros.py index 3efd524..c2bd09c 100644 --- a/plugins/module_utils/routeros.py +++ b/plugins/module_utils/routeros.py @@ -9,6 +9,7 @@ import json from ansible.module_utils.common.text.converters import to_native from ansible.module_utils.basic import env_fallback from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList +from ansible_collections.community.routeros.plugins.module_utils.version import LooseVersion from ansible.module_utils.connection import Connection, ConnectionError _DEVICE_CONFIGS = {} @@ -103,6 +104,16 @@ def to_commands(module, commands): return transform(commands) +def should_add_leading_space(module): + """Determines whether adding a leading space to the command is needed + to workaround prompt bug in 6.49 <= ROS < 7.2""" + capabilities = get_capabilities(module) + network_os_version = capabilities.get('device_info', {}).get('network_os_version') + if network_os_version is None: + return False + return LooseVersion('6.49') <= LooseVersion(network_os_version) < LooseVersion('7.2') + + def run_commands(module, commands, check_rc=True): responses = list() connection = get_connection(module) @@ -117,6 +128,9 @@ def run_commands(module, commands, check_rc=True): prompt = None answer = None + if should_add_leading_space(module): + command = " " + command + try: out = connection.get(command, prompt, answer) except ConnectionError as exc: diff --git a/plugins/module_utils/version.py b/plugins/module_utils/version.py new file mode 100644 index 0000000..dc01ffe --- /dev/null +++ b/plugins/module_utils/version.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Felix Fontein +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +"""Provide version object to compare version numbers.""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can +# remove the _version.py file, and replace the following import by +# +# from ansible.module_utils.compat.version import LooseVersion + +from ._version import LooseVersion # noqa: F401, pylint: disable=unused-import From 07a331179290d584c786a4dba0aef9166405f10f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 23 Mar 2023 21:28:31 +0100 Subject: [PATCH 119/365] Prepare 2.8.0 release. --- changelogs/fragments/2.8.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.8.0.yml diff --git a/changelogs/fragments/2.8.0.yml b/changelogs/fragments/2.8.0.yml new file mode 100644 index 0000000..56de6d9 --- /dev/null +++ b/changelogs/fragments/2.8.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. diff --git a/galaxy.yml b/galaxy.yml index 1118e2c..85e5e63 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.7.0 +version: 2.8.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From c1bd819db5cb4629dfa1637a54dbb9829d30e4cd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 23 Mar 2023 22:14:38 +0100 Subject: [PATCH 120/365] Release 2.8.0. --- CHANGELOG.rst | 25 +++++++++++++++++ changelogs/changelog.yaml | 28 +++++++++++++++++++ .../153-ip_firewall_layer7-protocol.yml | 2 -- .../154-ip-dhcp-client-dhcp-options.yml | 3 -- .../fragments/156-ip_dhcp-server_network.yml | 2 -- .../fragments/158-ipv6_settings-disable.yml | 2 -- changelogs/fragments/159-snmp_community.yml | 3 -- .../161-workaround-prompt-with-space.yml | 3 -- changelogs/fragments/2.8.0.yml | 1 - .../fragments/remove-unneeded-imports.yml | 2 -- 10 files changed, 53 insertions(+), 18 deletions(-) delete mode 100644 changelogs/fragments/153-ip_firewall_layer7-protocol.yml delete mode 100644 changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml delete mode 100644 changelogs/fragments/156-ip_dhcp-server_network.yml delete mode 100644 changelogs/fragments/158-ipv6_settings-disable.yml delete mode 100644 changelogs/fragments/159-snmp_community.yml delete mode 100644 changelogs/fragments/161-workaround-prompt-with-space.yml delete mode 100644 changelogs/fragments/2.8.0.yml delete mode 100644 changelogs/fragments/remove-unneeded-imports.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 31a28c0..fe262d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,31 @@ Community RouterOS Release Notes .. contents:: Topics +v2.8.0 +====== + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). +- api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). +- api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). +- api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/158). +- api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). +- command - workaround for extra characters in stdout in RouterOS versions between 6.49 and 7.1.5 (https://github.com/ansible-collections/community.routeros/issues/62, https://github.com/ansible-collections/community.routeros/pull/161). + +Bugfixes +-------- + +- api_info, api_modify - fix default and remove behavior for ``dhcp-options`` in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, https://github.com/ansible-collections/community.routeros/pull/154). +- api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154). +- various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149). + v2.7.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index ad9c9f8..a8b58ac 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -397,3 +397,31 @@ releases: - 144-paths.yml - 2.7.0.yml release_date: '2023-01-14' + 2.8.0: + changes: + bugfixes: + - api_info, api_modify - fix default and remove behavior for ``dhcp-options`` + in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, + https://github.com/ansible-collections/community.routeros/pull/154). + - api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154). + - various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149). + minor_changes: + - api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). + - api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). + - api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). + - api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/158). + - api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). + - command - workaround for extra characters in stdout in RouterOS versions between + 6.49 and 7.1.5 (https://github.com/ansible-collections/community.routeros/issues/62, + https://github.com/ansible-collections/community.routeros/pull/161). + release_summary: Bugfix and feature release. + fragments: + - 153-ip_firewall_layer7-protocol.yml + - 154-ip-dhcp-client-dhcp-options.yml + - 156-ip_dhcp-server_network.yml + - 158-ipv6_settings-disable.yml + - 159-snmp_community.yml + - 161-workaround-prompt-with-space.yml + - 2.8.0.yml + - remove-unneeded-imports.yml + release_date: '2023-03-23' diff --git a/changelogs/fragments/153-ip_firewall_layer7-protocol.yml b/changelogs/fragments/153-ip_firewall_layer7-protocol.yml deleted file mode 100644 index 694c7ea..0000000 --- a/changelogs/fragments/153-ip_firewall_layer7-protocol.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). diff --git a/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml b/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml deleted file mode 100644 index 016eb15..0000000 --- a/changelogs/fragments/154-ip-dhcp-client-dhcp-options.yml +++ /dev/null @@ -1,3 +0,0 @@ -bugfixes: - - "api_info, api_modify - fix default and remove behavior for ``dhcp-options`` in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, https://github.com/ansible-collections/community.routeros/pull/154)." - - "api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154)." diff --git a/changelogs/fragments/156-ip_dhcp-server_network.yml b/changelogs/fragments/156-ip_dhcp-server_network.yml deleted file mode 100644 index d89f834..0000000 --- a/changelogs/fragments/156-ip_dhcp-server_network.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). diff --git a/changelogs/fragments/158-ipv6_settings-disable.yml b/changelogs/fragments/158-ipv6_settings-disable.yml deleted file mode 100644 index 11e2c3e..0000000 --- a/changelogs/fragments/158-ipv6_settings-disable.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/158). diff --git a/changelogs/fragments/159-snmp_community.yml b/changelogs/fragments/159-snmp_community.yml deleted file mode 100644 index b8d678e..0000000 --- a/changelogs/fragments/159-snmp_community.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). - - api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). diff --git a/changelogs/fragments/161-workaround-prompt-with-space.yml b/changelogs/fragments/161-workaround-prompt-with-space.yml deleted file mode 100644 index beafb31..0000000 --- a/changelogs/fragments/161-workaround-prompt-with-space.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - command - workaround for extra characters in stdout in RouterOS versions between 6.49 and 7.1.5 - (https://github.com/ansible-collections/community.routeros/issues/62, https://github.com/ansible-collections/community.routeros/pull/161). diff --git a/changelogs/fragments/2.8.0.yml b/changelogs/fragments/2.8.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/2.8.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. diff --git a/changelogs/fragments/remove-unneeded-imports.yml b/changelogs/fragments/remove-unneeded-imports.yml deleted file mode 100644 index 320f914..0000000 --- a/changelogs/fragments/remove-unneeded-imports.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149)." From 189088611dc53206a1e1a92a93eede9a7d8ae038 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 4 Apr 2023 08:12:43 +0200 Subject: [PATCH 121/365] Update CI matrix: add stable-2.15 (#163) * Add ignore files for bumped devel version. * Update CI matrix. --- .github/workflows/ansible-test.yml | 11 +++++------ tests/sanity/ignore-2.16.txt | 1 + tests/sanity/ignore-2.16.txt.license | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 tests/sanity/ignore-2.16.txt create mode 100644 tests/sanity/ignore-2.16.txt.license diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 9f46e08..a5b3519 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -32,6 +32,7 @@ jobs: - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 - devel # Ansible-test on various stable branches does not yet work well with cgroups v2. # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 @@ -75,6 +76,7 @@ jobs: - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 - devel steps: @@ -127,17 +129,14 @@ jobs: # 2.12 - ansible: stable-2.12 python: 3.8 - - ansible: stable-2.12 - python: "3.10" # 2.13 - - ansible: stable-2.13 - python: 3.8 - ansible: stable-2.13 python: "3.10" # 2.14 - ansible: stable-2.14 - python: 3.9 - - ansible: stable-2.14 + python: "3.9" + # 2.15 + - ansible: stable-2.15 python: "3.11" steps: diff --git a/tests/sanity/ignore-2.16.txt b/tests/sanity/ignore-2.16.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.16.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.16.txt.license b/tests/sanity/ignore-2.16.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.16.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From 0caec0f2c30cf83c9bcdd6208db59124cc287d4f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 16 Apr 2023 16:08:57 +0200 Subject: [PATCH 122/365] Fix bad comma. (#166) --- tests/sanity/extra/update-docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sanity/extra/update-docs.json b/tests/sanity/extra/update-docs.json index f6f87b7..f37b95f 100644 --- a/tests/sanity/extra/update-docs.json +++ b/tests/sanity/extra/update-docs.json @@ -2,7 +2,7 @@ "include_symlinks": false, "prefixes": [ "docs/docsite/rst/api-guide.rst", - "plugins/modules/", + "plugins/modules/" ], "output": "path-line-column-message", } From a7f47c041976befc50f6adaeb58fd1d4805e85bc Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 16 Apr 2023 18:01:19 +0200 Subject: [PATCH 123/365] More fixes. --- tests/sanity/extra/update-docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sanity/extra/update-docs.json b/tests/sanity/extra/update-docs.json index f37b95f..029699f 100644 --- a/tests/sanity/extra/update-docs.json +++ b/tests/sanity/extra/update-docs.json @@ -4,5 +4,5 @@ "docs/docsite/rst/api-guide.rst", "plugins/modules/" ], - "output": "path-line-column-message", + "output": "path-line-column-message" } From e5eff0b90e91ae8af5810915de03910ac5920580 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 16 Apr 2023 18:16:19 +0200 Subject: [PATCH 124/365] Fix order. --- plugins/modules/api_info.py | 2 +- plugins/modules/api_modify.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 3220a52..50228c0 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -98,11 +98,11 @@ options: - ip firewall address-list - ip firewall connection tracking - ip firewall filter + - ip firewall layer7-protocol - ip firewall mangle - ip firewall nat - ip firewall raw - ip firewall service-port - - ip firewall layer7-protocol - ip hotspot service-port - ip ipsec identity - ip ipsec peer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 0bf2c71..5d410e9 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -103,11 +103,11 @@ options: - ip firewall address-list - ip firewall connection tracking - ip firewall filter + - ip firewall layer7-protocol - ip firewall mangle - ip firewall nat - ip firewall raw - ip firewall service-port - - ip firewall layer7-protocol - ip hotspot service-port - ip ipsec identity - ip ipsec peer From dd1e48c388c65d40e898fb65f034d404d7d08289 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 16 Apr 2023 19:01:53 +0200 Subject: [PATCH 125/365] Do extra docs validation; explicitly disallow semantic markup in docs (#165) * Do extra docs validation. Explicitly disallow semantic markup in docs. * Forgot to add new requirement. * Improve test. * TEMP - make CI fail. * Remove unnecessary import. * Make sure ANSIBLE_COLLECTIONS_PATH is set. * Revert "TEMP - make CI fail." This reverts commit 445c56e7e1bcd844be59f1df9df00a9c8334ff55. * Make sure sanity tests from older Ansible versions don't complain. --- tests/sanity/extra/extra-docs.json | 5 ++++- tests/sanity/extra/extra-docs.py | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/sanity/extra/extra-docs.json b/tests/sanity/extra/extra-docs.json index c2e612e..9a28d17 100644 --- a/tests/sanity/extra/extra-docs.json +++ b/tests/sanity/extra/extra-docs.json @@ -1,10 +1,13 @@ { "include_symlinks": false, "prefixes": [ - "docs/docsite/" + "docs/docsite/", + "plugins/", + "roles/" ], "output": "path-line-column-message", "requirements": [ + "ansible-core", "antsibull-docs" ] } diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py index 6731049..c636beb 100755 --- a/tests/sanity/extra/extra-docs.py +++ b/tests/sanity/extra/extra-docs.py @@ -13,9 +13,14 @@ import subprocess def main(): """Main entry point.""" - if not os.path.isdir(os.path.join('docs', 'docsite')): - return - p = subprocess.run(['antsibull-docs', 'lint-collection-docs', '.'], check=False) + env = os.environ.copy() + suffix = ':{env}'.format(env=env["ANSIBLE_COLLECTIONS_PATH"]) if 'ANSIBLE_COLLECTIONS_PATH' in env else '' + env['ANSIBLE_COLLECTIONS_PATH'] = '{root}{suffix}'.format(root=os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd()))), suffix=suffix) + p = subprocess.run( + ['antsibull-docs', 'lint-collection-docs', '--plugin-docs', '--disallow-semantic-markup', '--skip-rstcheck', '.'], + env=env, + check=False, + ) if p.returncode not in (0, 3): print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) From 4ec0945e550e74158e1e74152c3cd25ce240d538 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 20 May 2023 12:11:45 +0200 Subject: [PATCH 126/365] Rewrite EE test workflow to use ansible-builder 3.0.0 (#171) * Rewrite EE test workflow to use ansible-builder 3.0.0. * Extend list of potential errors. --- .github/workflows/ee.yml | 97 +++++++++++++++++++++++------ tests/ee/roles/smoke/tasks/main.yml | 6 +- 2 files changed, 82 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index bc85932..406703a 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -22,14 +22,58 @@ env: jobs: build: - name: Build and test EE (Ⓐ${{ matrix.runner_tag }}) + name: Build and test EE (${{ matrix.name }}) strategy: + fail-fast: false matrix: - runner_tag: - - devel - - stable-2.12-latest - - stable-2.11-latest - - stable-2.9-latest + name: + - '' + ansible_core: + - '' + ansible_runner: + - '' + base_image: + - '' + pre_base: + - '' + extra_vars: + - '' + other_deps: + - '' + exclude: + - ansible_core: '' + include: + - name: ansible-core devel @ RHEL UBI 9 + ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz + ansible_runner: ansible-runner + base_image: docker.io/redhat/ubi9:latest + pre_base: '"#"' + - name: ansible-core 2.15 @ Rocky Linux 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz + ansible_runner: ansible-runner + base_image: quay.io/rockylinux/rockylinux:9 + pre_base: '"#"' + - name: ansible-core 2.14 @ CentOS Stream 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.14.tar.gz + ansible_runner: ansible-runner + base_image: quay.io/centos/centos:stream9 + pre_base: '"#"' + - name: ansible-core 2.13 @ RHEL UBI 8 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.13.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python39 python39-pip python39-wheel python39-cryptography + base_image: docker.io/redhat/ubi8:latest + pre_base: '"#"' + - name: ansible-core 2.12 @ CentOS Stream 8 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.12.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python39 python39-pip python39-wheel python39-cryptography + base_image: quay.io/centos/centos:stream8 + pre_base: '"#"' runs-on: ubuntu-latest steps: - name: Check out code @@ -40,7 +84,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-builder and ansible-navigator run: pip install ansible-builder ansible-navigator @@ -62,11 +106,6 @@ jobs: ' working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - - name: Install collection dependencies - run: git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ansible_collections/ansible/netcommon - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # run: ansible-galaxy collection install ansible.netcommon -p . - - name: Build collection run: | ansible-galaxy collection build --output-path ../../../ @@ -79,11 +118,26 @@ jobs: # EE config cat > execution-environment.yml < requirements.yml < ansible-navigator run --mode stdout + --container-engine docker --pull-policy never --set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true --execution-environment-image test-ee:latest -v all.yml + ${{ matrix.extra_vars }} working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee diff --git a/tests/ee/roles/smoke/tasks/main.yml b/tests/ee/roles/smoke/tasks/main.yml index 072f4cc..b992c8e 100644 --- a/tests/ee/roles/smoke/tasks/main.yml +++ b/tests/ee/roles/smoke/tasks/main.yml @@ -16,7 +16,11 @@ assert: that: - result is failed - - "'Error while connecting: [Errno 111] Connection refused' == result.msg" + - result.msg in potential_errors + vars: + potential_errors: + - "Error while connecting: [Errno 111] Connection refused" + - "Error while connecting: [Errno 99] Cannot assign requested address" - name: Run command module community.routeros.command: From 2b8c66b9836aa97a3ea2f847106a8135e83bcd2a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 May 2023 13:48:07 +0200 Subject: [PATCH 127/365] Switch to Ansible Galaxy compatible requirements files for tests. (#173) --- tests/{ => integration}/requirements.yml | 4 +--- tests/unit/requirements.yml | 7 +++++++ 2 files changed, 8 insertions(+), 3 deletions(-) rename tests/{ => integration}/requirements.yml (73%) create mode 100644 tests/unit/requirements.yml diff --git a/tests/requirements.yml b/tests/integration/requirements.yml similarity index 73% rename from tests/requirements.yml rename to tests/integration/requirements.yml index 0186af5..6a22736 100644 --- a/tests/requirements.yml +++ b/tests/integration/requirements.yml @@ -3,7 +3,5 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -integration_tests_dependencies: -- ansible.netcommon -unit_tests_dependencies: +collections: - ansible.netcommon diff --git a/tests/unit/requirements.yml b/tests/unit/requirements.yml new file mode 100644 index 0000000..6a22736 --- /dev/null +++ b/tests/unit/requirements.yml @@ -0,0 +1,7 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +collections: +- ansible.netcommon From 42ea132d603cd728d19496a413b935c35d2e5672 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 9 Jun 2023 06:03:42 +0200 Subject: [PATCH 128/365] Fix bug in preprocessing when wrapped line is appended to a non-existing entry. (#177) --- changelogs/fragments/177-facts-parsing.yml | 2 ++ plugins/modules/facts.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/177-facts-parsing.yml diff --git a/changelogs/fragments/177-facts-parsing.yml b/changelogs/fragments/177-facts-parsing.yml new file mode 100644 index 0000000..d3dd481 --- /dev/null +++ b/changelogs/fragments/177-facts-parsing.yml @@ -0,0 +1,2 @@ +bugfixes: + - "facts - do not crash in CLI output preprocessing in unexpected situations during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, https://github.com/ansible-collections/community.routeros/pull/177)." diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 7b1cd0d..85c0b37 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -391,7 +391,7 @@ class Interfaces(FactsBase): for line in data.split('\n'): if len(line) == 0 or line[:5] == 'Flags': continue - elif not re.match(self.WRAPPED_LINE_RE, line): + elif not preprocessed or not re.match(self.WRAPPED_LINE_RE, line): preprocessed.append(line) else: preprocessed[-1] += line @@ -468,7 +468,7 @@ class Routing(FactsBase): for line in data.split('\n'): if len(line) == 0 or line[:5] == 'Flags': continue - elif not re.match(self.WRAPPED_LINE_RE, line): + elif not preprocessed or not re.match(self.WRAPPED_LINE_RE, line): preprocessed.append(line) else: preprocessed[-1] += line From 9cfb31ab186addfd5b038e82388fb41e9ce147a7 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 9 Jun 2023 06:08:40 +0200 Subject: [PATCH 129/365] Prepare 2.8.1 release. --- changelogs/fragments/2.8.1.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.8.1.yml diff --git a/changelogs/fragments/2.8.1.yml b/changelogs/fragments/2.8.1.yml new file mode 100644 index 0000000..8ce9aa9 --- /dev/null +++ b/changelogs/fragments/2.8.1.yml @@ -0,0 +1 @@ +release_summary: Bugfix release. diff --git a/galaxy.yml b/galaxy.yml index 85e5e63..ad952a8 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.8.0 +version: 2.8.1 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From d098c209e7de2580043d750370f2ffeb3a2a3cbe Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 14 Jun 2023 17:35:45 +0200 Subject: [PATCH 130/365] Release 2.8.1. --- CHANGELOG.rst | 13 +++++++++++++ changelogs/changelog.yaml | 11 +++++++++++ changelogs/fragments/177-facts-parsing.yml | 2 -- changelogs/fragments/2.8.1.yml | 1 - 4 files changed, 24 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/177-facts-parsing.yml delete mode 100644 changelogs/fragments/2.8.1.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fe262d8..7c9d3c9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,19 @@ Community RouterOS Release Notes .. contents:: Topics +v2.8.1 +====== + +Release Summary +--------------- + +Bugfix release. + +Bugfixes +-------- + +- facts - do not crash in CLI output preprocessing in unexpected situations during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, https://github.com/ansible-collections/community.routeros/pull/177). + v2.8.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index a8b58ac..48ce5da 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -425,3 +425,14 @@ releases: - 2.8.0.yml - remove-unneeded-imports.yml release_date: '2023-03-23' + 2.8.1: + changes: + bugfixes: + - facts - do not crash in CLI output preprocessing in unexpected situations + during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, + https://github.com/ansible-collections/community.routeros/pull/177). + release_summary: Bugfix release. + fragments: + - 177-facts-parsing.yml + - 2.8.1.yml + release_date: '2023-06-14' diff --git a/changelogs/fragments/177-facts-parsing.yml b/changelogs/fragments/177-facts-parsing.yml deleted file mode 100644 index d3dd481..0000000 --- a/changelogs/fragments/177-facts-parsing.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "facts - do not crash in CLI output preprocessing in unexpected situations during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, https://github.com/ansible-collections/community.routeros/pull/177)." diff --git a/changelogs/fragments/2.8.1.yml b/changelogs/fragments/2.8.1.yml deleted file mode 100644 index 8ce9aa9..0000000 --- a/changelogs/fragments/2.8.1.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix release. From af28e6419f4eea3441654c30eb69c99033ec3786 Mon Sep 17 00:00:00 2001 From: derdeagle Date: Mon, 19 Jun 2023 13:12:20 +0200 Subject: [PATCH 131/365] Fixes #179: Add missing /tool/e-mail parameter "tls" (#180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #179: Add missing /tool/e-mail parameter "tls" In the [documentation](https://help.mikrotik.com/docs/display/ROS/E-mail#Email-Properties) the parameter "tls" is mentioned but it cannot be used. The old "start-tls" parameter is not mentioned there (only on the [old documentation](https://wiki.mikrotik.com/wiki/Manual:Tools/email#Properties)). Trying to use the paramter "tls" lead to the erro message `FAILED! => {"changed": false, "msg": "Unknown key \"tls\"."}`. * Add changelog fragment * Update changelogs/fragments/180-fix-tls-in-tool-email.yml As suggested by felixfontein Co-authored-by: Felix Fontein --------- Co-authored-by: Johannes Münch Co-authored-by: Felix Fontein --- changelogs/fragments/180-fix-tls-in-tool-email.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/180-fix-tls-in-tool-email.yml diff --git a/changelogs/fragments/180-fix-tls-in-tool-email.yml b/changelogs/fragments/180-fix-tls-in-tool-email.yml new file mode 100644 index 0000000..0a69498 --- /dev/null +++ b/changelogs/fragments/180-fix-tls-in-tool-email.yml @@ -0,0 +1,2 @@ +bugfixes: + - api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` path (https://github.com/ansible-collections/community.routeros/issues/179, https://github.com/ansible-collections/community.routeros/pull/180). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0d3e82f..59e5b5c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2451,6 +2451,7 @@ PATHS = { 'password': KeyInfo(default=''), 'port': KeyInfo(default=25), 'start-tls': KeyInfo(default=False), + 'tls': KeyInfo(default=False), 'user': KeyInfo(default=''), }, ), From b7ef2fe1f87565003f405c663956b638de80e09e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 19 Jun 2023 13:13:14 +0200 Subject: [PATCH 132/365] Prepare 2.8.2 release. --- changelogs/fragments/2.8.2.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.8.2.yml diff --git a/changelogs/fragments/2.8.2.yml b/changelogs/fragments/2.8.2.yml new file mode 100644 index 0000000..8ce9aa9 --- /dev/null +++ b/changelogs/fragments/2.8.2.yml @@ -0,0 +1 @@ +release_summary: Bugfix release. diff --git a/galaxy.yml b/galaxy.yml index ad952a8..6f47b5f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.8.1 +version: 2.8.2 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 1fb691581961e3b6d4718daa08bacde6acacb4e0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 19 Jun 2023 16:42:18 +0200 Subject: [PATCH 133/365] Release 2.8.2. --- CHANGELOG.rst | 13 +++++++++++++ changelogs/changelog.yaml | 11 +++++++++++ changelogs/fragments/180-fix-tls-in-tool-email.yml | 2 -- changelogs/fragments/2.8.2.yml | 1 - 4 files changed, 24 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/180-fix-tls-in-tool-email.yml delete mode 100644 changelogs/fragments/2.8.2.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7c9d3c9..d82c58e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,19 @@ Community RouterOS Release Notes .. contents:: Topics +v2.8.2 +====== + +Release Summary +--------------- + +Bugfix release. + +Bugfixes +-------- + +- api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` path (https://github.com/ansible-collections/community.routeros/issues/179, https://github.com/ansible-collections/community.routeros/pull/180). + v2.8.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 48ce5da..e09fa3e 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -436,3 +436,14 @@ releases: - 177-facts-parsing.yml - 2.8.1.yml release_date: '2023-06-14' + 2.8.2: + changes: + bugfixes: + - api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` + path (https://github.com/ansible-collections/community.routeros/issues/179, + https://github.com/ansible-collections/community.routeros/pull/180). + release_summary: Bugfix release. + fragments: + - 180-fix-tls-in-tool-email.yml + - 2.8.2.yml + release_date: '2023-06-19' diff --git a/changelogs/fragments/180-fix-tls-in-tool-email.yml b/changelogs/fragments/180-fix-tls-in-tool-email.yml deleted file mode 100644 index 0a69498..0000000 --- a/changelogs/fragments/180-fix-tls-in-tool-email.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` path (https://github.com/ansible-collections/community.routeros/issues/179, https://github.com/ansible-collections/community.routeros/pull/180). diff --git a/changelogs/fragments/2.8.2.yml b/changelogs/fragments/2.8.2.yml deleted file mode 100644 index 8ce9aa9..0000000 --- a/changelogs/fragments/2.8.2.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix release. From 08c8c7ecc89106b665cdbaf95e41c6e377531455 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 21 Jun 2023 08:19:31 +0200 Subject: [PATCH 134/365] CI: Bump hard-coded Python versions to 3.11; drop Python 3.9 with devel. (#183) --- .github/workflows/ansible-test.yml | 5 ++--- .github/workflows/extra-tests.yml | 2 +- .github/workflows/import-galaxy.yml | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index a5b3519..e50b2f8 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -109,7 +109,6 @@ jobs: ansible: - devel python: - - 3.9 - "3.10" - "3.11" include: @@ -134,10 +133,10 @@ jobs: python: "3.10" # 2.14 - ansible: stable-2.14 - python: "3.9" + python: "3.11" # 2.15 - ansible: stable-2.15 - python: "3.11" + python: "3.9" steps: - name: >- diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 0bbcdbb..952ebd3 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index 55a7310..d38b157 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check @@ -71,7 +71,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install ansible-core run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check From 2e78a207e928a80d8551a28dba2d60e161a90fa9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Jun 2023 13:18:08 +0200 Subject: [PATCH 135/365] Use semantic markup (#185) * Enable semantic markup. * Use semantic markup. * Break long lines. * Add ignore entries. * Ignore docs build error. --- .github/workflows/docs-pr.yml | 2 + changelogs/fragments/semantic-markup.yml | 5 +++ docs/docsite/rst/api-guide.rst | 8 ++-- docs/docsite/rst/quoting.rst | 2 +- docs/docsite/rst/ssh-guide.rst | 2 +- plugins/doc_fragments/api.py | 24 +++++----- plugins/filter/list_to_dict.yml | 6 +-- plugins/modules/api.py | 56 +++++++++++++----------- plugins/modules/api_facts.py | 46 +++++++++---------- plugins/modules/api_find_and_modify.py | 16 +++---- plugins/modules/api_info.py | 18 ++++---- plugins/modules/api_modify.py | 20 ++++----- plugins/modules/command.py | 12 ++--- plugins/modules/facts.py | 50 ++++++++++----------- tests/sanity/extra/extra-docs.py | 2 +- tests/sanity/ignore-2.10.txt | 3 ++ tests/sanity/ignore-2.9.txt | 3 ++ 17 files changed, 146 insertions(+), 129 deletions(-) create mode 100644 changelogs/fragments/semantic-markup.yml diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 4b3f1f3..14a917a 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -32,6 +32,8 @@ jobs: init-extra-html-theme-options: | documentation_home_url=https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/branch/main/ render-file-line: '> * `$` [$](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr/${{ github.event.number }}/$)' + provide-link-targets: | + ansible_collections.ansible.netcommon.network_cli_connection__parameter-ssh_type publish-docs-gh-pages: # for now we won't run this on forks diff --git a/changelogs/fragments/semantic-markup.yml b/changelogs/fragments/semantic-markup.yml new file mode 100644 index 0000000..e8a448f --- /dev/null +++ b/changelogs/fragments/semantic-markup.yml @@ -0,0 +1,5 @@ +known_issues: + - Ansible markup will show up in raw form on ansible-doc text output for ansible-core + before 2.15. If you have trouble deciphering the documentation markup, please + upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on + https://docs.ansible.com/ansible/devel/collections/community/routeros/. diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index f3bb629..a672060 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -105,11 +105,11 @@ Here all three tasks will use the options set for the module defaults group. Setting up encryption --------------------- -It is recommended to always use ``tls: true`` when connecting with the API, even if you are only connecting to the device through a trusted network. The following options control how TLS/SSL is used: +It is recommended to always use :ansopt:`tls=true` when connecting with the API, even if you are only connecting to the device through a trusted network. The following options control how TLS/SSL is used: -:force_no_cert: Setting to ``true`` connects to the device without a certificate. **This is discouraged to use in production and is susceptible to Man-in-the-Middle attacks**, but might be useful when setting the device up. The default value is ``false``. -:validate_certs: Setting to ``false`` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is ``true``. -:validate_cert_hostname: Setting to ``false`` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to ``true``; the default ``false`` is chosen for backwards compatibility to an older version of the module. +:force_no_cert: Setting to :ansval:`true` connects to the device without a certificate. **This is discouraged to use in production and is susceptible to Man-in-the-Middle attacks**, but might be useful when setting the device up. The default value is :ansval:`false`. +:validate_certs: Setting to :ansval:`false` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is :ansval:`true`. +:validate_cert_hostname: Setting to :ansval:`false` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to :ansval:`true`; the default :ansval:`false` is chosen for backwards compatibility to an older version of the module. :ca_path: If you are not using a commerically trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate. We recommend to create a CA certificate that is used to sign the certificates for your RouterOS devices, and have the certificates include the correct hostname(s), including the IP of the device. That way, you can fully enable TLS and be sure that you always talk to the correct device. diff --git a/docs/docsite/rst/quoting.rst b/docs/docsite/rst/quoting.rst index 3091fc8..1356f7b 100644 --- a/docs/docsite/rst/quoting.rst +++ b/docs/docsite/rst/quoting.rst @@ -16,4 +16,4 @@ The community.routeros collection provides a set of Jinja2 filter plugins which - The :ref:`community.routeros.quote_argument filter ` quotes an argument with or without a value: ``'comment=this is a "comment"' | community.routeros.quote_argument == 'comment="this is a \\"comment\\""'``. - The :ref:`community.routeros.join filter ` quotes a list of arguments and joins them to one string: ``['foo=bar', 'comment=foo is bar'] | community.routeros.join == 'foo=bar comment="foo is bar"'``. - The :ref:`community.routeros.split filter ` splits a command into a list of arguments (with or without values): ``'foo=bar comment="foo is bar"' | community.routeros.split == ['foo=bar', 'comment=foo is bar']`` -- The :ref:`community.routeros.list_to_dict filter ` splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: ``require_assignment`` (default value ``true``) allows to accept arguments without values when set to ``false``; and ``skip_empty_values`` (default value ``false``) allows to skip arguments whose value is empty. +- The :ref:`community.routeros.list_to_dict filter ` splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: :ansopt:`community.routeros.list_to_dict#filter:require_assignment` (default value :ansval:`true`) allows to accept arguments without values when set to :ansval:`false`; and :ansopt:`community.routeros.list_to_dict#filter:skip_empty_values` (default value :ansval:`false`) allows to skip arguments whose value is empty. diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index bdbdbfe..17254c5 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -31,7 +31,7 @@ Important notes 3. When using the :ref:`community.routeros.command module ` module, make sure to not specify too long commands. Alternatively, add something like ``+cet512w`` to the username (replace ``admin`` with ``admin+cet512w``) to tell RouterOS to not wrap before 512 characters in a line (`see issue for details `__). -4. Finally, the :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its ``ssh_type`` option to ``libssh`` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. +4. Finally, the :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type`` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. Setting up an inventory ----------------------- diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index dea374b..7f77e8f 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -43,48 +43,48 @@ options: - ssl port: description: - - RouterOS api port. If I(tls) is set, port will apply to TLS/SSL connection. - - Defaults are C(8728) for the HTTP API, and C(8729) for the HTTPS API. + - RouterOS api port. If O(tls) is set, port will apply to TLS/SSL connection. + - Defaults are V(8728) for the HTTP API, and V(8729) for the HTTPS API. type: int force_no_cert: description: - - Set to C(true) to connect without a certificate when I(tls=true). - - See also I(validate_certs). + - Set to V(true) to connect without a certificate when O(tls=true). + - See also O(validate_certs). - B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible to Man-in-the-Middle attacks, because the keys used in the exchange are not authenticated. Instead of simply connecting without a certificate to "make things work" have a look at - I(validate_certs) and I(ca_path). + O(validate_certs) and O(ca_path). type: bool default: false version_added: 2.4.0 validate_certs: description: - - Set to C(false) to skip validation of TLS certificates. - - See also I(validate_cert_hostname). Only used when I(tls=true). + - Set to V(false) to skip validation of TLS certificates. + - See also O(validate_cert_hostname). Only used when O(tls=true). - B(Note:) instead of simply deactivating certificate validations to "make things work", please consider creating your own CA certificate and using it to sign certificates used - for your router. You can tell the module about your CA certificate with the I(ca_path) + for your router. You can tell the module about your CA certificate with the O(ca_path) option. type: bool default: true version_added: 1.2.0 validate_cert_hostname: description: - - Set to C(true) to validate hostnames in certificates. - - See also I(validate_certs). Only used when I(tls=true) and I(validate_certs=true). + - Set to V(true) to validate hostnames in certificates. + - See also O(validate_certs). Only used when O(tls=true) and O(validate_certs=true). type: bool default: false version_added: 1.2.0 ca_path: description: - PEM formatted file that contains a CA certificate to be used for certificate validation. - - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). + - See also O(validate_cert_hostname). Only used when O(tls=true) and O(validate_certs=true). type: path version_added: 1.2.0 encoding: description: - Use the specified encoding when communicating with the RouterOS device. - - Default is C(ASCII). Note that C(UTF-8) requires librouteros 3.2.1 or newer. + - Default is V(ASCII). Note that V(UTF-8) requires librouteros 3.2.1 or newer. type: str default: ASCII version_added: 2.1.0 diff --git a/plugins/filter/list_to_dict.yml b/plugins/filter/list_to_dict.yml index 920414c..6e7992d 100644 --- a/plugins/filter/list_to_dict.yml +++ b/plugins/filter/list_to_dict.yml @@ -12,18 +12,18 @@ DOCUMENTATION: options: _input: description: - - A list of assignments. Can be the result of the C(community.routeros.split) filter. + - A list of assignments. Can be the result of the P(community.routeros.split#filter) filter. type: list elements: string required: true require_assignment: description: - - Allows to accept arguments without values when set to C(false). + - Allows to accept arguments without values when set to V(false). type: boolean default: true skip_empty_values: description: - - Allows to skip arguments whose value is empty when set to C(true). + - Allows to skip arguments whose value is empty when set to V(true). type: boolean default: false author: diff --git a/plugins/modules/api.py b/plugins/modules/api.py index f9c619f..65b9796 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -17,7 +17,7 @@ description: - Ansible module for RouterOS API with the Python C(librouteros) library. - This module can add, remove, update, query and execute arbitrary command in RouterOS via API. notes: - - I(add), I(remove), I(update), I(cmd) and I(query) are mutually exclusive. + - O(add), O(remove), O(update), O(cmd), and O(query) are mutually exclusive. - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules for more specific modifications, and the M(community.routeros.api_info) module for a more controlled way of returning all entries for a path. @@ -40,26 +40,26 @@ options: description: - Main path for all other arguments. - If other arguments are not set, api will return all items in selected path. - - Example C(ip address). Equivalent of RouterOS CLI C(/ip address print). + - Example V(ip address). Equivalent of RouterOS CLI C(/ip address print). required: true type: str add: description: - Will add selected arguments in selected path to RouterOS config. - - Example C(address=1.1.1.1/32 interface=ether1). + - Example V(address=1.1.1.1/32 interface=ether1). - Equivalent in RouterOS CLI C(/ip address add address=1.1.1.1/32 interface=ether1). type: str remove: description: - Remove config/value from RouterOS by '.id'. - - Example C(*03) will remove config/value with C(id=*03) in selected path. + - Example V(*03) will remove config/value with C(id=*03) in selected path. - Equivalent in RouterOS CLI C(/ip address remove numbers=1). - Note C(number) in RouterOS CLI is different from C(.id). type: str update: description: - Update config/value in RouterOS by '.id' in selected path. - - Example C(.id=*03 address=1.1.1.3/32) and path C(ip address) will replace existing ip address with C(.id=*03). + - Example V(.id=*03 address=1.1.1.3/32) and path V(ip address) will replace existing ip address with C(.id=*03). - Equivalent in RouterOS CLI C(/ip address set address=1.1.1.3/32 numbers=1). - Note C(number) in RouterOS CLI is different from C(.id). type: str @@ -67,11 +67,11 @@ options: description: - Query given path for selected query attributes from RouterOS aip. - WHERE is key word which extend query. WHERE format is key operator value - with spaces. - - WHERE valid operators are C(==) or C(eq), C(!=) or C(not), C(>) or C(more), C(<) or C(less). - - Example path C(ip address) and query C(.id address) will return only C(.id) and C(address) for all items in C(ip address) path. - - Example path C(ip address) and query C(.id address WHERE address == 1.1.1.3/32). - will return only C(.id) and C(address) for items in C(ip address) path, where address is eq to 1.1.1.3/32. - - Example path C(interface) and query C(mtu name WHERE mut > 1400) will + - WHERE valid operators are V(==) or V(eq), V(!=) or V(not), V(>) or V(more), V(<) or V(less). + - Example path V(ip address) and query V(.id address) will return only C(.id) and C(address) for all items in V(ip address) path. + - Example path V(ip address) and query V(.id address WHERE address == 1.1.1.3/32). + will return only C(.id) and C(address) for items in V(ip address) path, where address is eq to 1.1.1.3/32. + - Example path V(interface) and query V(mtu name WHERE mut > 1400) will return only interfaces C(mtu,name) where mtu is bigger than 1400. - Equivalent in RouterOS CLI C(/interface print where mtu > 1400). type: str @@ -84,65 +84,69 @@ options: attributes: description: - The list of attributes to return. - - Every attribute used in a I(where) clause need to be listed here. + - Every attribute used in a O(extended_query.where[]) clause need to be listed here. type: list elements: str required: true where: description: - Allows to restrict the objects returned. - - The conditions here must all match. An I(or) condition needs at least one of its conditions to match. + - The conditions here must all match. An O(extended_query.where[].or) condition needs at least one of its conditions to match. type: list elements: dict suboptions: attribute: description: - - The attribute to match. Must be part of I(attributes). - - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + - The attribute to match. Must be part of O(extended_query.attributes). + - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is), + and O(extended_query.where[].value) have to be specified. type: str is: description: - The operator to use for matching. - - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more). - - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list. - - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more). + - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].value) must be a list. + - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is), + and O(extended_query.where[].value) have to be specified. type: str choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"] value: description: - - The value to compare to. Must be a list for I(is=in). - - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + - The value to compare to. Must be a list for O(extended_query.where[].is=in). + - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is), + and O(extended_query.where[].value) have to be specified. type: raw or: description: - A list of conditions so that at least one of them has to match. - - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified. + - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is), + and O(extended_query.where[].value) have to be specified. type: list elements: dict suboptions: attribute: description: - - The attribute to match. Must be part of I(attributes). + - The attribute to match. Must be part of O(extended_query.attributes). type: str required: true is: description: - The operator to use for matching. - - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more). - - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list. + - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more). + - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].or[].value) must be a list. type: str choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"] required: true value: description: - - The value to compare to. Must be a list for I(is=in). + - The value to compare to. Must be a list for O(extended_query.where[].or[].is=in). type: raw required: true cmd: description: - Execute any/arbitrary command in selected path, after the command we can add C(.id). - - Example path C(system script) and cmd C(run .id=*03) is equivalent in RouterOS CLI C(/system script run number=0). - - Example path C(ip address) and cmd C(print) is equivalent in RouterOS CLI C(/ip address print). + - Example path V(system script) and cmd V(run .id=*03) is equivalent in RouterOS CLI C(/system script run number=0). + - Example path V(ip address) and cmd V(print) is equivalent in RouterOS CLI C(/ip address print). type: str seealso: - ref: ansible_collections.community.routeros.docsite.quoting diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index f297236..296621e 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -41,9 +41,9 @@ options: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include - C(all), C(hardware), C(interfaces), and C(routing). + V(all), V(hardware), V(interfaces), and V(routing). - Can specify a list of values to include a larger subset. - Values can also be used with an initial C(!) to specify that a + Values can also be used with an initial V(!) to specify that a specific subset should not be collected. required: false default: @@ -89,93 +89,93 @@ ansible_facts: # default ansible_net_model: description: The model name returned from the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_serialnum: description: The serial number of the remote device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_version: description: The operating system version running on the remote device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_hostname: description: The configured hostname of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_arch: description: The CPU architecture of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_uptime: description: The uptime of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_cpu_load: description: Current CPU load. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str # hardware ansible_net_spacefree_mb: description: The available disk space on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: dict ansible_net_spacetotal_mb: description: The total disk space on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: dict ansible_net_memfree_mb: description: The available free memory on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: int ansible_net_memtotal_mb: description: The total memory on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: int # interfaces ansible_net_all_ipv4_addresses: description: All IPv4 addresses configured on the device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: list ansible_net_all_ipv6_addresses: description: All IPv6 addresses configured on the device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: list ansible_net_interfaces: description: A hash of all interfaces running on the system. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: dict ansible_net_neighbors: description: The list of neighbors from the remote device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: dict # routing ansible_net_bgp_peer: description: A dictionary with BGP peer information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_bgp_vpnv4_route: description: A dictionary with BGP vpnv4 route information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_bgp_instance: description: A dictionary with BGP instance information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_route: description: A dictionary for routes in all routing tables. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_ospf_instance: description: A dictionary with OSPF instances. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_ospf_neighbor: description: A dictionary with OSPF neighbors. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict """ diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 0be3f70..176c943 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -21,7 +21,7 @@ description: or change multiple entries in different ways in one step. notes: - "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that - there are at least N such values, you can use I(require_matches_min=N) together with I(allow_no_matches=true). + there are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true). This will make the module fail if there are less than N such entries, but not if there is no match. The latter case is needed for idempotency of the task: once the values have been changed, there should be no further match." extends_documentation_fragment: @@ -40,21 +40,21 @@ options: path: description: - Path to query. - - An example value is C(ip address). This is equivalent to running C(/ip address) in the RouterOS CLI. + - An example value is V(ip address). This is equivalent to running C(/ip address) in the RouterOS CLI. required: true type: str find: description: - Fields to search for. - - The module will only consider entries in the given I(path) that match all fields provided here. - - Use YAML C(~), or prepend keys with C(!), to specify an unset value. + - The module will only consider entries in the given O(path) that match all fields provided here. + - Use YAML V(~), or prepend keys with V(!), to specify an unset value. - Note that if the dictionary specified here is empty, every entry in the path will be matched. required: true type: dict values: description: - - On all entries matching the conditions in I(find), set the keys of this option to the values specified here. - - Use YAML C(~), or prepend keys with C(!), to specify to unset a value. + - On all entries matching the conditions in O(find), set the keys of this option to the values specified here. + - Use YAML V(~), or prepend keys with V(!), to specify to unset a value. required: true type: dict require_matches_min: @@ -72,7 +72,7 @@ options: allow_no_matches: description: - Whether to allow that no match is found. - - If not specified, this value is induced from whether I(require_matches_min) is 0 or larger. + - If not specified, this value is induced from whether O(require_matches_min) is 0 or larger. type: bool seealso: - module: community.routeros.api @@ -146,7 +146,7 @@ new_data: returned: success match_count: description: - - The number of entries that matched the criteria in I(find). + - The number of entries that matched the criteria in O(find). sample: 1 type: int returned: success diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 50228c0..4fda150 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -18,9 +18,9 @@ version_added: 2.2.0 description: - Allows to retrieve information for a path using the API. - This can be used to backup a path to restore it with the M(community.routeros.api_modify) module. - - Entries are normalized, dynamic and builtin entries are not returned. Use the I(handle_disabled) and - I(hide_defaults) options to control normalization, the I(include_dynamic) and I(include_builtin) options to also return - dynamic resp. builtin entries, and use I(unfiltered) to return all fields including counters. + - Entries are normalized, dynamic and builtin entries are not returned. Use the O(handle_disabled) and + O(hide_defaults) options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return + dynamic resp. builtin entries, and use O(unfiltered) to return all fields including counters. - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). @@ -37,7 +37,7 @@ options: path: description: - Path to query. - - An example value is C(ip address). This is equivalent to running C(/ip address print) in the RouterOS CLI. + - An example value is V(ip address). This is equivalent to running C(/ip address print) in the RouterOS CLI. required: true type: str choices: @@ -194,9 +194,9 @@ options: handle_disabled: description: - How to handle unset values. - - C(exclamation) prepends the keys with C(!) in the output with value C(null). - - C(null-value) uses the regular key with value C(null). - - C(omit) omits these values from the result. + - V(exclamation) prepends the keys with V(!) in the output with value V(null). + - V(null-value) uses the regular key with value V(null). + - V(omit) omits these values from the result. type: str choices: - exclamation @@ -212,14 +212,14 @@ options: description: - Whether to include dynamic values. - By default, they are not returned, and the C(dynamic) keys are omitted. - - If set to C(true), they are returned as well, and the C(dynamic) keys are returned as well. + - If set to V(true), they are returned as well, and the C(dynamic) keys are returned as well. type: bool default: false include_builtin: description: - Whether to include builtin values. - By default, they are not returned, and the C(builtin) keys are omitted. - - If set to C(true), they are returned as well, and the C(builtin) keys are returned as well. + - If set to V(true), they are returned as well, and the C(builtin) keys are returned as well. type: bool default: false version_added: 2.4.0 diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 5d410e9..d21d31f 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -42,7 +42,7 @@ options: path: description: - Path to query. - - An example value is C(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI. + - An example value is V(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI. required: true type: str choices: @@ -200,15 +200,15 @@ options: elements: dict ensure_order: description: - - Whether to ensure the same order of the config as present in I(data). - - Requires I(handle_absent_entries=remove). + - Whether to ensure the same order of the config as present in O(data). + - Requires O(handle_absent_entries=remove). type: bool default: false handle_absent_entries: description: - - How to handle entries that are present in the current config, but not in I(data). - - C(ignore) ignores them. - - C(remove) removes them. + - How to handle entries that are present in the current config, but not in O(data). + - V(ignore) ignores them. + - V(remove) removes them. type: str choices: - ignore @@ -216,11 +216,11 @@ options: default: ignore handle_entries_content: description: - - For a single entry in I(data), this describes how to handle fields that are not mentioned + - For a single entry in O(data), this describes how to handle fields that are not mentioned in that entry, but appear in the actual config. - - If C(ignore), they are not modified. - - If C(remove), they are removed. If at least one cannot be removed, the module will fail. - - If C(remove_as_much_as_possible), all that can be removed will be removed. The ones that + - If V(ignore), they are not modified. + - If V(remove), they are removed. If at least one cannot be removed, the module will fail. + - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that cannot be removed will be kept. type: str choices: diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 8442602..52b916b 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -40,7 +40,7 @@ options: description: - List of commands to send to the remote RouterOS device over the configured provider. The resulting output from the command - is returned. If the I(wait_for) argument is provided, the + is returned. If the O(wait_for) argument is provided, the module is not returned until the condition is satisfied or the number of retries has expired. required: true @@ -57,11 +57,11 @@ options: elements: str match: description: - - The I(match) argument is used in conjunction with the - I(wait_for) argument to specify the match policy. Valid - values are C(all) or C(any). If the value is set to C(all) + - The O(match) argument is used in conjunction with the + O(wait_for) argument to specify the match policy. Valid + values are V(all) or V(any). If the value is set to V(all) then all conditionals in the wait_for must be satisfied. If - the value is set to C(any) then only one of the values must be + the value is set to V(any) then only one of the values must be satisfied. default: all choices: ['any', 'all'] @@ -71,7 +71,7 @@ options: - Specifies the number of retries a command should by tried before it is considered failed. The command is run on the target device every retry and evaluated against the - I(wait_for) conditions. + O(wait_for) conditions. default: 10 type: int interval: diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 85c0b37..a47e354 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -31,9 +31,9 @@ options: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include - C(all), C(hardware), C(config), C(interfaces), and C(routing). + V(all), V(hardware), V(config), V(interfaces), and V(routing). - Can specify a list of values to include a larger subset. - Values can also be used with an initial C(!) to specify that a + Values can also be used with an initial V(!) to specify that a specific subset should not be collected. required: false default: @@ -75,55 +75,55 @@ ansible_facts: # default ansible_net_model: description: The model name returned from the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_serialnum: description: The serial number of the remote device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_version: description: The operating system version running on the remote device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_hostname: description: The configured hostname of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_arch: description: The CPU architecture of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_uptime: description: The uptime of the device. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str ansible_net_cpu_load: description: Current CPU load. - returned: I(gather_subset) contains C(default) + returned: O(gather_subset) contains V(default) type: str # hardware ansible_net_spacefree_mb: description: The available disk space on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: dict ansible_net_spacetotal_mb: description: The total disk space on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: dict ansible_net_memfree_mb: description: The available free memory on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: int ansible_net_memtotal_mb: description: The total memory on the remote device in MiB. - returned: I(gather_subset) contains C(hardware) + returned: O(gather_subset) contains V(hardware) type: int # config ansible_net_config: description: The current active config from the device. - returned: I(gather_subset) contains C(config) + returned: O(gather_subset) contains V(config) type: str ansible_net_config_nonverbose: @@ -132,52 +132,52 @@ ansible_facts: - This value is idempotent in the sense that if the facts module is run twice and the device's config was not changed between the runs, the value is identical. This is achieved by running C(/export) and stripping the timestamp from the comment in the first line. - returned: I(gather_subset) contains C(config) + returned: O(gather_subset) contains V(config) type: str version_added: 1.2.0 # interfaces ansible_net_all_ipv4_addresses: description: All IPv4 addresses configured on the device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: list ansible_net_all_ipv6_addresses: description: All IPv6 addresses configured on the device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: list ansible_net_interfaces: description: A hash of all interfaces running on the system. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: dict ansible_net_neighbors: description: The list of neighbors from the remote device. - returned: I(gather_subset) contains C(interfaces) + returned: O(gather_subset) contains V(interfaces) type: dict # routing ansible_net_bgp_peer: description: A dictionary with BGP peer information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_bgp_vpnv4_route: description: A dictionary with BGP vpnv4 route information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_bgp_instance: description: A dictionary with BGP instance information. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_route: description: A dictionary for routes in all routing tables. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_ospf_instance: description: A dictionary with OSPF instances. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict ansible_net_ospf_neighbor: description: A dictionary with OSPF neighbors. - returned: I(gather_subset) contains C(routing) + returned: O(gather_subset) contains V(routing) type: dict """ import re diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py index c636beb..251e6d7 100755 --- a/tests/sanity/extra/extra-docs.py +++ b/tests/sanity/extra/extra-docs.py @@ -17,7 +17,7 @@ def main(): suffix = ':{env}'.format(env=env["ANSIBLE_COLLECTIONS_PATH"]) if 'ANSIBLE_COLLECTIONS_PATH' in env else '' env['ANSIBLE_COLLECTIONS_PATH'] = '{root}{suffix}'.format(root=os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd()))), suffix=suffix) p = subprocess.run( - ['antsibull-docs', 'lint-collection-docs', '--plugin-docs', '--disallow-semantic-markup', '--skip-rstcheck', '.'], + ['antsibull-docs', 'lint-collection-docs', '--plugin-docs', '--skip-rstcheck', '.'], env=env, check=False, ) diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt index 876765a..ece5b29 100644 --- a/tests/sanity/ignore-2.10.txt +++ b/tests/sanity/ignore-2.10.txt @@ -1,3 +1,6 @@ +docs/docsite/rst/api-guide.rst rstcheck +docs/docsite/rst/quoting.rst rstcheck +docs/docsite/rst/ssh-guide.rst rstcheck update-docs.py compile-2.6 update-docs.py compile-2.7 update-docs.py compile-3.5 diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt index 876765a..ece5b29 100644 --- a/tests/sanity/ignore-2.9.txt +++ b/tests/sanity/ignore-2.9.txt @@ -1,3 +1,6 @@ +docs/docsite/rst/api-guide.rst rstcheck +docs/docsite/rst/quoting.rst rstcheck +docs/docsite/rst/ssh-guide.rst rstcheck update-docs.py compile-2.6 update-docs.py compile-2.7 update-docs.py compile-3.5 From 2333efcf0f0f6f11d5f496529137509f617f9bd9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Jun 2023 20:42:09 +0200 Subject: [PATCH 136/365] Be lenient. --- .github/workflows/docs-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index 7408bbb..e4595dd 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -28,7 +28,7 @@ jobs: uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main with: collection-name: community.routeros - init-lenient: false + init-lenient: true init-fail-on-error: true squash-hierarchy: true init-project: Community.Routeros Collection From 9d505ce903d1850b0115ef2b3549d8ef889bcd5f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Jun 2023 20:54:23 +0200 Subject: [PATCH 137/365] Fix docs. --- docs/docsite/rst/ssh-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index 17254c5..f7297f9 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -31,7 +31,7 @@ Important notes 3. When using the :ref:`community.routeros.command module ` module, make sure to not specify too long commands. Alternatively, add something like ``+cet512w`` to the username (replace ``admin`` with ``admin+cet512w``) to tell RouterOS to not wrap before 512 characters in a line (`see issue for details `__). -4. Finally, the :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type`` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. +4. Finally, the :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. Setting up an inventory ----------------------- From ce7b2ef144a2d013e110fa7f462e7dc8bfe78f38 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 22 Jun 2023 21:24:40 +0200 Subject: [PATCH 138/365] Prepare 2.8.3. --- changelogs/fragments/2.8.3.yml | 11 +++++++++++ galaxy.yml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.8.3.yml diff --git a/changelogs/fragments/2.8.3.yml b/changelogs/fragments/2.8.3.yml new file mode 100644 index 0000000..6dc4f63 --- /dev/null +++ b/changelogs/fragments/2.8.3.yml @@ -0,0 +1,11 @@ +release_summary: | + Maintenance release with updated documentation. + + From this version on, community.routeros is using the new `Ansible semantic markup + `__ + in its documentation. If you look at documentation with the ansible-doc CLI tool + from ansible-core before 2.15, please note that it does not render the markup + correctly. You should be still able to read it in most cases, but you need + ansible-core 2.15 or later to see it as it is intended. Alternatively you can + look at `the devel docsite `__ + for the rendered HTML version of the documentation of the latest release. diff --git a/galaxy.yml b/galaxy.yml index 6f47b5f..a42a1d2 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.8.2 +version: 2.8.3 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 61c6b1dca8a9935724835e033aa4c588cef175ab Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 27 Jun 2023 07:19:22 +0200 Subject: [PATCH 139/365] Release 2.8.3. --- CHANGELOG.rst | 23 ++++++++++++++++ changelogs/changelog.yaml | 34 ++++++++++++++++++++++++ changelogs/fragments/2.8.3.yml | 11 -------- changelogs/fragments/semantic-markup.yml | 5 ---- 4 files changed, 57 insertions(+), 16 deletions(-) delete mode 100644 changelogs/fragments/2.8.3.yml delete mode 100644 changelogs/fragments/semantic-markup.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d82c58e..f5bf29e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,29 @@ Community RouterOS Release Notes .. contents:: Topics +v2.8.3 +====== + +Release Summary +--------------- + +Maintenance release with updated documentation. + +From this version on, community.routeros is using the new `Ansible semantic markup +`__ +in its documentation. If you look at documentation with the ansible-doc CLI tool +from ansible-core before 2.15, please note that it does not render the markup +correctly. You should be still able to read it in most cases, but you need +ansible-core 2.15 or later to see it as it is intended. Alternatively you can +look at `the devel docsite `__ +for the rendered HTML version of the documentation of the latest release. + + +Known Issues +------------ + +- Ansible markup will show up in raw form on ansible-doc text output for ansible-core before 2.15. If you have trouble deciphering the documentation markup, please upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on https://docs.ansible.com/ansible/devel/collections/community/routeros/. + v2.8.2 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index e09fa3e..b7668a5 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -447,3 +447,37 @@ releases: - 180-fix-tls-in-tool-email.yml - 2.8.2.yml release_date: '2023-06-19' + 2.8.3: + changes: + known_issues: + - Ansible markup will show up in raw form on ansible-doc text output for ansible-core + before 2.15. If you have trouble deciphering the documentation markup, please + upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on + https://docs.ansible.com/ansible/devel/collections/community/routeros/. + release_summary: 'Maintenance release with updated documentation. + + + From this version on, community.routeros is using the new `Ansible semantic + markup + + `__ + + in its documentation. If you look at documentation with the ansible-doc CLI + tool + + from ansible-core before 2.15, please note that it does not render the markup + + correctly. You should be still able to read it in most cases, but you need + + ansible-core 2.15 or later to see it as it is intended. Alternatively you + can + + look at `the devel docsite `__ + + for the rendered HTML version of the documentation of the latest release. + + ' + fragments: + - 2.8.3.yml + - semantic-markup.yml + release_date: '2023-06-27' diff --git a/changelogs/fragments/2.8.3.yml b/changelogs/fragments/2.8.3.yml deleted file mode 100644 index 6dc4f63..0000000 --- a/changelogs/fragments/2.8.3.yml +++ /dev/null @@ -1,11 +0,0 @@ -release_summary: | - Maintenance release with updated documentation. - - From this version on, community.routeros is using the new `Ansible semantic markup - `__ - in its documentation. If you look at documentation with the ansible-doc CLI tool - from ansible-core before 2.15, please note that it does not render the markup - correctly. You should be still able to read it in most cases, but you need - ansible-core 2.15 or later to see it as it is intended. Alternatively you can - look at `the devel docsite `__ - for the rendered HTML version of the documentation of the latest release. diff --git a/changelogs/fragments/semantic-markup.yml b/changelogs/fragments/semantic-markup.yml deleted file mode 100644 index e8a448f..0000000 --- a/changelogs/fragments/semantic-markup.yml +++ /dev/null @@ -1,5 +0,0 @@ -known_issues: - - Ansible markup will show up in raw form on ansible-doc text output for ansible-core - before 2.15. If you have trouble deciphering the documentation markup, please - upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on - https://docs.ansible.com/ansible/devel/collections/community/routeros/. From 13e68fc906d243ac70891eee0899942525d93dca Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 12 Jul 2023 08:12:37 +0200 Subject: [PATCH 140/365] Disable EE with ansible-core devel for now until UBI 9 has Python 3.10 support. (#187) --- .github/workflows/ee.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 406703a..e49f301 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -43,11 +43,11 @@ jobs: exclude: - ansible_core: '' include: - - name: ansible-core devel @ RHEL UBI 9 - ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz - ansible_runner: ansible-runner - base_image: docker.io/redhat/ubi9:latest - pre_base: '"#"' + # - name: ansible-core devel @ RHEL UBI 9 + # ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz + # ansible_runner: ansible-runner + # base_image: docker.io/redhat/ubi9:latest + # pre_base: '"#"' - name: ansible-core 2.15 @ Rocky Linux 9 ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz ansible_runner: ansible-runner From 553a77aa918d3dbbf68c8626786121c51c5ef0c3 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 12 Jul 2023 19:24:44 +0200 Subject: [PATCH 141/365] Install and use Python 3.11 on RHEL UBI 9. (#188) --- .github/workflows/ee.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index e49f301..ae9a3db 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -43,11 +43,15 @@ jobs: exclude: - ansible_core: '' include: - # - name: ansible-core devel @ RHEL UBI 9 - # ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz - # ansible_runner: ansible-runner - # base_image: docker.io/redhat/ubi9:latest - # pre_base: '"#"' + - name: ansible-core devel @ RHEL UBI 9 + ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography + python_path: "/usr/bin/python3.11" + base_image: docker.io/redhat/ubi9:latest + pre_base: '"#"' - name: ansible-core 2.15 @ Rocky Linux 9 ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz ansible_runner: ansible-runner From e570c582d0b95fab3c5c65bc67081954e3da909d Mon Sep 17 00:00:00 2001 From: derdeagle Date: Sun, 16 Jul 2023 21:15:48 +0200 Subject: [PATCH 142/365] Fixes #189: Add missing /snmp parameter "engine-id-suffix" (#190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #189: Add missing /snmp parameter "engine-id-suffix" * Fixes #189: Add changelog fragment after getting PR ID * Update changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Johannes Münch Co-authored-by: Felix Fontein --- changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml diff --git a/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml b/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml new file mode 100644 index 0000000..021f7f0 --- /dev/null +++ b/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml @@ -0,0 +1,2 @@ +bugfixes: + - api_modify, api_info - add missing parameter ``engine-id-suffix`` for the ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, https://github.com/ansible-collections/community.routeros/pull/190). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 59e5b5c..3925dec 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2280,6 +2280,7 @@ PATHS = { 'contact': KeyInfo(default=''), 'enabled': KeyInfo(default=False), 'engine-id': KeyInfo(default=''), + 'engine-id-suffix': KeyInfo(default=''), 'location': KeyInfo(default=''), 'src-address': KeyInfo(default='::'), 'trap-community': KeyInfo(default='public'), From 6e62283120c96e4738c928ab7ff9b452b1d4fbab Mon Sep 17 00:00:00 2001 From: derdeagle Date: Sun, 23 Jul 2023 21:27:32 +0200 Subject: [PATCH 143/365] Fixes #191: Add path 'ip traffic-flow target' (#192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #191: Add path 'ip traffic-flow target' * Fixes #191: Add changelog fragment * Fixes #192: Change changetype from major to minor as it is only adding a path and neither breaking existing things nor adding completely new functionality --------- Co-authored-by: Johannes Münch --- .../192-add-ip_traffic-flow_target-path.yml | 2 ++ plugins/module_utils/_api_data.py | 14 ++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 18 insertions(+) create mode 100644 changelogs/fragments/192-add-ip_traffic-flow_target-path.yml diff --git a/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml b/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml new file mode 100644 index 0000000..aabe76e --- /dev/null +++ b/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, https://github.com/ansible-collections/community.routeros/pull/192). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 3925dec..eb26b97 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1846,6 +1846,20 @@ PATHS = { 'udp-length': KeyInfo(default=True), }, ), + ('ip', 'traffic-flow', 'target'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'dst-address': KeyInfo(), + 'port': KeyInfo(default=2055), + 'src-address': KeyInfo(), + 'v9-template-refresh': KeyInfo(default=20), + 'v9-template-timeout': KeyInfo(), + 'version': KeyInfo(), + }, + ), ('ip', 'upnp'): APIData( single_value=True, fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 4fda150..7cb755d 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -123,6 +123,7 @@ options: - ip tftp settings - ip traffic-flow - ip traffic-flow ipfix + - ip traffic-flow target - ip upnp - ipv6 address - ipv6 dhcp-client diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d21d31f..03bd86f 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -128,6 +128,7 @@ options: - ip tftp settings - ip traffic-flow - ip traffic-flow ipfix + - ip traffic-flow target - ip upnp - ipv6 address - ipv6 dhcp-client From d6f90e69379bd78c7ea698419110a9c9932541c8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 23 Jul 2023 21:49:31 +0200 Subject: [PATCH 144/365] Prepare 2.9.0 release. --- changelogs/fragments/2.9.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.9.0.yml diff --git a/changelogs/fragments/2.9.0.yml b/changelogs/fragments/2.9.0.yml new file mode 100644 index 0000000..56de6d9 --- /dev/null +++ b/changelogs/fragments/2.9.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. diff --git a/galaxy.yml b/galaxy.yml index a42a1d2..2dc6366 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.8.3 +version: 2.9.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 53bb84ba2a7ba606d4b2ba39baaafd7f831fe8d0 Mon Sep 17 00:00:00 2001 From: derdeagle Date: Sat, 12 Aug 2023 15:57:00 +0200 Subject: [PATCH 145/365] Fixes #193: Add caps-man channel and caps-man manager interface (#194) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #193: Add caps-man channel and caps-man manager interface Adding the caps-man channel path from scratch. Activating the caps-man manager interface path. * Add changelog fragment and documentation for both paths --------- Co-authored-by: Johannes Münch --- ...channel-and-caps-man_manager_interface.yml | 2 ++ plugins/module_utils/_api_data.py | 26 ++++++++++++++++--- plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml diff --git a/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml b/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml new file mode 100644 index 0000000..7717f28 --- /dev/null +++ b/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, https://github.com/ansible-collections/community.routeros/pull/194). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index eb26b97..d57ddae 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -797,6 +797,23 @@ PATHS = { 'vlan-mode': KeyInfo(can_disable=True), }, ), + ('caps-man', 'channel'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'band': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'control-channel-width': KeyInfo(can_disable=True), + 'extension-channel': KeyInfo(can_disable=True), + 'frequency': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'reselect-interval': KeyInfo(can_disable=True), + 'save-selected': KeyInfo(can_disable=True), + 'secondary-frequency': KeyInfo(can_disable=True), + 'skip-dfs-channels': KeyInfo(can_disable=True), + 'tx-power': KeyInfo(can_disable=True), + }, + ), ('caps-man', 'configuration'): APIData( fully_understood=True, primary_keys=('name', ), @@ -884,12 +901,13 @@ PATHS = { }, ), ('caps-man', 'manager', 'interface'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('interface', ), fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'forbid': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'forbid': KeyInfo(default=False), 'interface': KeyInfo(), }, ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 7cb755d..31db39e 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -44,9 +44,11 @@ options: # BEGIN PATH LIST - caps-man aaa - caps-man access-list + - caps-man channel - caps-man configuration - caps-man datapath - caps-man manager + - caps-man manager interface - caps-man provisioning - caps-man security - certificate settings diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 03bd86f..d5c319b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -49,9 +49,11 @@ options: # BEGIN PATH LIST - caps-man aaa - caps-man access-list + - caps-man channel - caps-man configuration - caps-man datapath - caps-man manager + - caps-man manager interface - caps-man provisioning - caps-man security - certificate settings From ed2f326a6a0ab1b9799e56f52745489358ecacf4 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 15 Aug 2023 07:10:11 +0200 Subject: [PATCH 146/365] Release 2.9.0. --- CHANGELOG.rst | 19 +++++++++++++++++++ changelogs/changelog.yaml | 19 +++++++++++++++++++ .../180-fix-engine-id-suffix-in-snmp.yml | 2 -- .../192-add-ip_traffic-flow_target-path.yml | 2 -- ...channel-and-caps-man_manager_interface.yml | 2 -- changelogs/fragments/2.9.0.yml | 1 - 6 files changed, 38 insertions(+), 7 deletions(-) delete mode 100644 changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml delete mode 100644 changelogs/fragments/192-add-ip_traffic-flow_target-path.yml delete mode 100644 changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml delete mode 100644 changelogs/fragments/2.9.0.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f5bf29e..4d784a1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,25 @@ Community RouterOS Release Notes .. contents:: Topics +v2.9.0 +====== + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, https://github.com/ansible-collections/community.routeros/pull/194). +- api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, https://github.com/ansible-collections/community.routeros/pull/192). + +Bugfixes +-------- + +- api_modify, api_info - add missing parameter ``engine-id-suffix`` for the ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, https://github.com/ansible-collections/community.routeros/pull/190). + v2.8.3 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index b7668a5..9e81f12 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -481,3 +481,22 @@ releases: - 2.8.3.yml - semantic-markup.yml release_date: '2023-06-27' + 2.9.0: + changes: + bugfixes: + - api_modify, api_info - add missing parameter ``engine-id-suffix`` for the + ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, + https://github.com/ansible-collections/community.routeros/pull/190). + minor_changes: + - api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man + manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, + https://github.com/ansible-collections/community.routeros/pull/194). + - api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, + https://github.com/ansible-collections/community.routeros/pull/192). + release_summary: Bugfix and feature release. + fragments: + - 180-fix-engine-id-suffix-in-snmp.yml + - 192-add-ip_traffic-flow_target-path.yml + - 194-add-caps-man_channel-and-caps-man_manager_interface.yml + - 2.9.0.yml + release_date: '2023-08-15' diff --git a/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml b/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml deleted file mode 100644 index 021f7f0..0000000 --- a/changelogs/fragments/180-fix-engine-id-suffix-in-snmp.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - api_modify, api_info - add missing parameter ``engine-id-suffix`` for the ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, https://github.com/ansible-collections/community.routeros/pull/190). diff --git a/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml b/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml deleted file mode 100644 index aabe76e..0000000 --- a/changelogs/fragments/192-add-ip_traffic-flow_target-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, https://github.com/ansible-collections/community.routeros/pull/192). diff --git a/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml b/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml deleted file mode 100644 index 7717f28..0000000 --- a/changelogs/fragments/194-add-caps-man_channel-and-caps-man_manager_interface.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, https://github.com/ansible-collections/community.routeros/pull/194). diff --git a/changelogs/fragments/2.9.0.yml b/changelogs/fragments/2.9.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/2.9.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. From 3b127b12fa6a0dc53a265ee05c87b967882b7ac7 Mon Sep 17 00:00:00 2001 From: hansmi Date: Wed, 16 Aug 2023 22:44:59 +0200 Subject: [PATCH 147/365] Sort "interface wireless security-profiles" with other wireless paths (#196) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the API data for `interface wireless security-profiles` to be in order with the other entries for `interface wireless …`. Signed-off-by: Michael Hanselmann --- plugins/module_utils/_api_data.py | 86 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d57ddae..ad6ef96 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -368,49 +368,6 @@ PATHS = { 'vrid': KeyInfo(default=1), }, ), - ('interface', 'wireless', 'security-profiles'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'authentication-types': KeyInfo(), - 'disable-pmkid': KeyInfo(), - 'eap-methods': KeyInfo(), - 'group-ciphers': KeyInfo(), - 'group-key-update': KeyInfo(), - 'interim-update': KeyInfo(), - 'management-protection': KeyInfo(), - 'management-protection-key': KeyInfo(), - 'mode': KeyInfo(), - 'mschapv2-password': KeyInfo(), - 'mschapv2-username': KeyInfo(), - 'name': KeyInfo(), - 'radius-called-format': KeyInfo(), - 'radius-eap-accounting': KeyInfo(), - 'radius-mac-accounting': KeyInfo(), - 'radius-mac-authentication': KeyInfo(), - 'radius-mac-caching': KeyInfo(), - 'radius-mac-format': KeyInfo(), - 'radius-mac-mode': KeyInfo(), - 'static-algo-0': KeyInfo(), - 'static-algo-1': KeyInfo(), - 'static-algo-2': KeyInfo(), - 'static-algo-3': KeyInfo(), - 'static-key-0': KeyInfo(), - 'static-key-1': KeyInfo(), - 'static-key-2': KeyInfo(), - 'static-key-3': KeyInfo(), - 'static-sta-private-algo': KeyInfo(), - 'static-sta-private-key': KeyInfo(), - 'static-transmit-key': KeyInfo(), - 'supplicant-identity': KeyInfo(), - 'tls-certificate': KeyInfo(), - 'tls-mode': KeyInfo(), - 'unicast-ciphers': KeyInfo(), - 'wpa-pre-shared-key': KeyInfo(), - 'wpa2-pre-shared-key': KeyInfo(), - }, - ), ('ip', 'hotspot', 'profile'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -1245,6 +1202,49 @@ PATHS = { 'static-virtual': KeyInfo(default=False), }, ), + ('interface', 'wireless', 'security-profiles'): APIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'authentication-types': KeyInfo(), + 'disable-pmkid': KeyInfo(), + 'eap-methods': KeyInfo(), + 'group-ciphers': KeyInfo(), + 'group-key-update': KeyInfo(), + 'interim-update': KeyInfo(), + 'management-protection': KeyInfo(), + 'management-protection-key': KeyInfo(), + 'mode': KeyInfo(), + 'mschapv2-password': KeyInfo(), + 'mschapv2-username': KeyInfo(), + 'name': KeyInfo(), + 'radius-called-format': KeyInfo(), + 'radius-eap-accounting': KeyInfo(), + 'radius-mac-accounting': KeyInfo(), + 'radius-mac-authentication': KeyInfo(), + 'radius-mac-caching': KeyInfo(), + 'radius-mac-format': KeyInfo(), + 'radius-mac-mode': KeyInfo(), + 'static-algo-0': KeyInfo(), + 'static-algo-1': KeyInfo(), + 'static-algo-2': KeyInfo(), + 'static-algo-3': KeyInfo(), + 'static-key-0': KeyInfo(), + 'static-key-1': KeyInfo(), + 'static-key-2': KeyInfo(), + 'static-key-3': KeyInfo(), + 'static-sta-private-algo': KeyInfo(), + 'static-sta-private-key': KeyInfo(), + 'static-transmit-key': KeyInfo(), + 'supplicant-identity': KeyInfo(), + 'tls-certificate': KeyInfo(), + 'tls-mode': KeyInfo(), + 'unicast-ciphers': KeyInfo(), + 'wpa-pre-shared-key': KeyInfo(), + 'wpa2-pre-shared-key': KeyInfo(), + }, + ), ('interface', 'wireless', 'sniffer'): APIData( single_value=True, fully_understood=True, From 2e1159b4c401525e5882681c1ff96761ea1f8d69 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:11:04 +0200 Subject: [PATCH 148/365] Support "address-list" and "match-subdomain" in static DNS records (#197) RouterOS 7.5 added `address-list` and `match-subdomain` as fields for static DNS records. Changelog: https://forum.mikrotik.com/viewtopic.php?t=188851 Signed-off-by: Michael Hanselmann --- ...197-dns-static-addrlist-matchsubdomain.yml | 2 + plugins/module_utils/_api_data.py | 2 + .../modules/test_api_find_and_modify.py | 14 +++++++ tests/unit/plugins/modules/test_api_modify.py | 37 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml diff --git a/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml b/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml new file mode 100644 index 0000000..e683b4c --- /dev/null +++ b/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ad6ef96..acd4378 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1408,10 +1408,12 @@ PATHS = { mutually_exclusive=[['name', 'regexp']], fields={ 'address': KeyInfo(), + 'address-list': KeyInfo(), 'cname': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'forward-to': KeyInfo(), + 'match-subdomain': KeyInfo(default=False), 'mx-exchange': KeyInfo(), 'mx-preference': KeyInfo(), 'name': KeyInfo(), diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index 384bc88..7587107 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -389,6 +389,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -397,6 +398,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -406,6 +408,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual(result['diff']['before']['values'], [ @@ -416,6 +419,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual(result['diff']['after']['values'], [ @@ -427,6 +431,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual(result['match_count'], 1) @@ -459,6 +464,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -467,6 +473,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -475,6 +482,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual('diff' in result, False) @@ -508,6 +516,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -516,6 +525,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -524,6 +534,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual(result['match_count'], 3) @@ -556,6 +567,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -564,6 +576,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -572,6 +585,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'ttl': '1d', 'disabled': False, 'dynamic': False, + 'match-subdomain': False, }, ]) self.assertEqual(result['match_count'], 3) diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index 7897973..ed9bfce 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -600,6 +600,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -607,6 +608,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -614,6 +616,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*NEW1', @@ -621,6 +624,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -661,6 +665,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -668,6 +673,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -675,6 +681,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*NEW1', @@ -682,6 +689,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -723,6 +731,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -730,6 +739,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -737,6 +747,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { 'name': 'router', @@ -782,6 +793,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -789,6 +801,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -796,6 +809,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -838,6 +852,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -845,6 +860,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -852,6 +868,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -894,6 +911,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -901,6 +919,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*NEW1', @@ -908,6 +927,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'cname': 'router.com.', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -951,6 +971,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -958,6 +979,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { 'name': 'router', @@ -1003,6 +1025,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -1011,6 +1034,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -1018,6 +1042,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -1060,6 +1085,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -1068,6 +1094,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry 2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*7', @@ -1075,6 +1102,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -1109,6 +1137,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -1144,6 +1173,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -1190,6 +1220,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*NEW1', @@ -1197,6 +1228,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'bar', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*A', @@ -1204,6 +1236,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*1', @@ -1212,6 +1245,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) @@ -1259,6 +1293,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.2', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { 'name': 'foo', @@ -1270,6 +1305,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'text': 'Router Text Entry', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, { '.id': '*1', @@ -1278,6 +1314,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', 'ttl': '1d', 'disabled': False, + 'match-subdomain': False, }, ]) From e4a21311a133a729a91b46536ae85aafd15cc065 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:15:38 +0200 Subject: [PATCH 149/365] Add "interface wireless" to API data (#195) The default values match those of RouterOS 7.11 on a Mikrotik RB924i-2nD-BT5&BG77 ("Knot"). They're cross-checked with upstream documentation[1]. [1] https://help.mikrotik.com/docs/display/ROS/Wireless+Interface Signed-off-by: Michael Hanselmann --- .../195-add-interface-wireless-data.yml | 2 + plugins/module_utils/_api_data.py | 98 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 102 insertions(+) create mode 100644 changelogs/fragments/195-add-interface-wireless-data.yml diff --git a/changelogs/fragments/195-add-interface-wireless-data.yml b/changelogs/fragments/195-add-interface-wireless-data.yml new file mode 100644 index 0000000..cdb91b5 --- /dev/null +++ b/changelogs/fragments/195-add-interface-wireless-data.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index acd4378..7a6e939 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1171,6 +1171,104 @@ PATHS = { 'public-key': KeyInfo(), }, ), + ('interface', 'wireless'): APIData( + fully_understood=True, + primary_keys=('name', ), + required_one_of=[['default-name', 'master-interface']], + fields={ + 'adaptive-noise-immunity': KeyInfo(default='none'), + 'allow-sharedkey': KeyInfo(default=False), + 'ampdu-priorities': KeyInfo(default=0), + 'amsdu-limit': KeyInfo(default=8192), + 'amsdu-threshold': KeyInfo(default=8192), + 'antenna-gain': KeyInfo(default=0), + 'antenna-mode': KeyInfo(), + 'area': KeyInfo(default=''), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'band': KeyInfo(), + 'basic-rates-a/g': KeyInfo(default='6Mbps'), + 'basic-rates-b': KeyInfo(default='1Mbps'), + 'bridge-mode': KeyInfo(default='enabled'), + 'channel-width': KeyInfo(default='20mhz'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'compression': KeyInfo(default=False), + 'country': KeyInfo(default='etsi'), + 'default-ap-tx-limit': KeyInfo(default=0), + 'default-authentication': KeyInfo(default=True), + 'default-client-tx-limit': KeyInfo(default=0), + 'default-forwarding': KeyInfo(default=True), + 'default-name': KeyInfo(), + 'disable-running-check': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'disconnect-timeout': KeyInfo(default='3s'), + 'distance': KeyInfo(default='dynamic'), + 'frame-lifetime': KeyInfo(default=0), + 'frequency': KeyInfo(), + 'frequency-mode': KeyInfo(default='regulatory-domain'), + 'frequency-offset': KeyInfo(default=0), + 'guard-interval': KeyInfo(default='any'), + 'hide-ssid': KeyInfo(default=False), + 'ht-basic-mcs': KeyInfo(), + 'ht-supported-mcs': KeyInfo(), + 'hw-fragmentation-threshold': KeyInfo(default='disabled'), + 'hw-protection-mode': KeyInfo(default='none'), + 'hw-protection-threshold': KeyInfo(default=0), + 'hw-retries': KeyInfo(default=7), + 'installation': KeyInfo(default='any'), + 'interworking-profile': KeyInfo(default='disabled'), + 'keepalive-frames': KeyInfo(default='enabled'), + 'l2mtu': KeyInfo(default=1600), + 'mac-address': KeyInfo(), + 'master-interface': KeyInfo(), + 'max-station-count': KeyInfo(default=2007), + 'mode': KeyInfo(default='ap-bridge'), + 'mtu': KeyInfo(default=1500), + 'multicast-buffering': KeyInfo(default='enabled'), + 'multicast-helper': KeyInfo(default='default'), + 'name': KeyInfo(), + 'noise-floor-threshold': KeyInfo(default='default'), + 'nv2-cell-radius': KeyInfo(default=30), + 'nv2-downlink-ratio': KeyInfo(default=50), + 'nv2-mode': KeyInfo(default='dynamic-downlink'), + 'nv2-noise-floor-offset': KeyInfo(default='default'), + 'nv2-preshared-key': KeyInfo(default=''), + 'nv2-qos': KeyInfo(default='default'), + 'nv2-queue-count': KeyInfo(default=2), + 'nv2-security': KeyInfo(default='disabled'), + 'nv2-sync-secret': KeyInfo(default=''), + 'on-fail-retry-time': KeyInfo(default='100ms'), + 'preamble-mode': KeyInfo(default='both'), + 'radio-name': KeyInfo(), + 'rate-selection': KeyInfo(default='advanced'), + 'rate-set': KeyInfo(default='default'), + 'running': KeyInfo(default=False), + 'rx-chains': KeyInfo(default='0,1'), + 'scan-list': KeyInfo(default='default'), + 'secondary-frequency': KeyInfo(default=''), + 'security-profile': KeyInfo(default='default'), + 'skip-dfs-channels': KeyInfo(default='disabled'), + 'ssid': KeyInfo(required=True), + 'station-bridge-clone-mac': KeyInfo(), + 'station-roaming': KeyInfo(default='disabled'), + 'supported-rates-a/g': KeyInfo(), + 'supported-rates-b': KeyInfo(), + 'tdma-period-size': KeyInfo(default=2), + 'tx-chains': KeyInfo(), + 'tx-power-mode': KeyInfo(default='default'), + 'update-stats-interval': KeyInfo(default='disabled'), + 'vlan-id': KeyInfo(default=1), + 'vlan-mode': KeyInfo(default='no-tag'), + 'wds-cost-range': KeyInfo(default='50-150'), + 'wds-default-bridge': KeyInfo(default='none'), + 'wds-default-cost': KeyInfo(default=100), + 'wds-ignore-ssid': KeyInfo(default=False), + 'wds-mode': KeyInfo(default='disabled'), + 'wireless-protocol': KeyInfo(default='any'), + 'wmm-support': KeyInfo(default='disabled'), + 'wps-mode': KeyInfo(default='push-button'), + }, + ), ('interface', 'wireless', 'align'): APIData( single_value=True, fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 31db39e..c44522b 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -79,6 +79,7 @@ options: - interface vrrp - interface wireguard - interface wireguard peers + - interface wireless - interface wireless align - interface wireless cap - interface wireless sniffer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d5c319b..e10aba4 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -84,6 +84,7 @@ options: - interface vrrp - interface wireguard - interface wireguard peers + - interface wireless - interface wireless align - interface wireless cap - interface wireless sniffer From 1aa41ad3755909ca5f212934d582fa27fb1c66be Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:17:14 +0200 Subject: [PATCH 150/365] Support "mode" in IPv4 neighbor discovery configuration (#198) RouterOS 7.7 added a `mode` parameter to the IPv4 neighbor discovery configuration. Changelog: https://forum.mikrotik.com/viewtopic.php?t=192427 Signed-off-by: Michael Hanselmann --- changelogs/fragments/198-ip-nd-mode.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/198-ip-nd-mode.yml diff --git a/changelogs/fragments/198-ip-nd-mode.yml b/changelogs/fragments/198-ip-nd-mode.yml new file mode 100644 index 0000000..5a892b2 --- /dev/null +++ b/changelogs/fragments/198-ip-nd-mode.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``mode`` property in ``ip neighbor discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 7a6e939..9675f2d 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1020,6 +1020,7 @@ PATHS = { fields={ 'discover-interface-list': KeyInfo(), 'lldp-med-net-policy-vlan': KeyInfo(default='disabled'), + 'mode': KeyInfo(default='tx-and-rx'), 'protocol': KeyInfo(default='cdp,lldp,mndp'), }, ), From 2164261e092725c7d8f2bb9e789e3a939920072e Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:17:49 +0200 Subject: [PATCH 151/365] Add "interface ppp-client" to API data (#199) The default values match those of RouterOS 7.11 on a Mikrotik RB924i-2nD-BT5&BG77 ("Knot"). Upstream documentation: https://help.mikrotik.com/docs/display/ROS/PPP Signed-off-by: Michael Hanselmann --- .../fragments/199-add-interface-pppclient.yml | 2 ++ plugins/module_utils/_api_data.py | 30 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 34 insertions(+) create mode 100644 changelogs/fragments/199-add-interface-pppclient.yml diff --git a/changelogs/fragments/199-add-interface-pppclient.yml b/changelogs/fragments/199-add-interface-pppclient.yml new file mode 100644 index 0000000..989ec9c --- /dev/null +++ b/changelogs/fragments/199-add-interface-pppclient.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``interface ppp-client`` path (https://github.com/ansible-collections/community.routeros/pull/199). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9675f2d..1cf5154 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -298,6 +298,36 @@ PATHS = { 'use-peer-dns': KeyInfo(), }, ), + ('interface', 'ppp-client'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'add-default-route': KeyInfo(default=True), + 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'data-channel': KeyInfo(default=0), + 'default-route-distance': KeyInfo(default=1), + 'dial-command': KeyInfo(default="ATDT"), + 'dial-on-demand': KeyInfo(default=True), + 'disabled': KeyInfo(default=True), + 'info-channel': KeyInfo(default=0), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1500), + 'max-mtu': KeyInfo(default=1500), + 'modem-init': KeyInfo(default=''), + 'mrru': KeyInfo(default='disabled'), + 'name': KeyInfo(), + 'null-modem': KeyInfo(default=False), + 'password': KeyInfo(default=''), + 'phone': KeyInfo(default=''), + 'pin': KeyInfo(default=''), + 'port': KeyInfo(), + 'profile': KeyInfo(default='default'), + 'running': KeyInfo(default=False), + 'use-peer-dns': KeyInfo(default=True), + 'user': KeyInfo(default=''), + }, + ), ('interface', 'pppoe-client'): APIData( fully_understood=True, primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index c44522b..9726ca6 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -72,6 +72,7 @@ options: - interface list - interface list member - interface ovpn-server server + - interface ppp-client - interface pppoe-client - interface pptp-server server - interface sstp-server server diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index e10aba4..28774d4 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -77,6 +77,7 @@ options: - interface list - interface list member - interface ovpn-server server + - interface ppp-client - interface pppoe-client - interface pptp-server server - interface sstp-server server From 343c4883c0a11a1f817ca6868c7d8550edc50944 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:19:11 +0200 Subject: [PATCH 152/365] Add support for "routing filter {rule|select-rule}" (#200) RouterOS 7 added route selections and filters (https://help.mikrotik.com/docs/display/ROS/Route+Selection+and+Filters). Signed-off-by: Michael Hanselmann --- .../fragments/200-add-routing-filter.yml | 2 ++ plugins/module_utils/_api_data.py | 24 +++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 30 insertions(+) create mode 100644 changelogs/fragments/200-add-routing-filter.yml diff --git a/changelogs/fragments/200-add-routing-filter.yml b/changelogs/fragments/200-add-routing-filter.yml new file mode 100644 index 0000000..90594df --- /dev/null +++ b/changelogs/fragments/200-add-routing-filter.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing filter rule`` and ``routing filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 1cf5154..201d0b1 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -591,6 +591,30 @@ PATHS = { 'use-radius': KeyInfo(default=False), }, ), + ('routing', 'filter', 'rule'): APIData( + fully_understood=True, + fields={ + 'chain': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'rule': KeyInfo(can_disable=True), + }, + ), + ('routing', 'filter', 'select-rule'): APIData( + fully_understood=True, + fields={ + 'chain': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'do-group-num': KeyInfo(can_disable=True), + 'do-group-prfx': KeyInfo(can_disable=True), + 'do-jump': KeyInfo(can_disable=True), + 'do-select-num': KeyInfo(can_disable=True), + 'do-select-prfx': KeyInfo(can_disable=True), + 'do-take': KeyInfo(can_disable=True), + 'do-where': KeyInfo(can_disable=True), + }, + ), ('routing', 'ospf', 'instance'): APIData( fully_understood=True, primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 9726ca6..9ddd202 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -149,6 +149,8 @@ options: - queue tree - radius incoming - routing bgp instance + - routing filter rule + - routing filter select-rule - routing mme - routing ospf area - routing ospf area range diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 28774d4..698b615 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -154,6 +154,8 @@ options: - queue tree - radius incoming - routing bgp instance + - routing filter rule + - routing filter select-rule - routing mme - routing ospf area - routing ospf area range From b0a4743de84bc03da821fcf437a0a6eeb3c94d1b Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 14:20:16 +0200 Subject: [PATCH 153/365] Add support for "user settings" (#201) The `user settings` path contains settings related to passwords. Signed-off-by: Michael Hanselmann --- changelogs/fragments/201-add-user-settings.yml | 2 ++ plugins/module_utils/_api_data.py | 8 ++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 12 insertions(+) create mode 100644 changelogs/fragments/201-add-user-settings.yml diff --git a/changelogs/fragments/201-add-user-settings.yml b/changelogs/fragments/201-add-user-settings.yml new file mode 100644 index 0000000..fdbc870 --- /dev/null +++ b/changelogs/fragments/201-add-user-settings.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 201d0b1..ee60e95 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2749,6 +2749,14 @@ PATHS = { 'use-radius': KeyInfo(default=False), }, ), + ('user', 'settings'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'minimum-categories': KeyInfo(), + 'minimum-password-length': KeyInfo(), + }, + ), ('queue', 'interface'): APIData( primary_keys=('interface', ), fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 9ddd202..9947103 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -191,6 +191,7 @@ options: - tool traffic-generator - user aaa - user group + - user settings # END PATH LIST unfiltered: description: diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 698b615..2fc7c57 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -196,6 +196,7 @@ options: - tool traffic-generator - user aaa - user group + - user settings # END PATH LIST data: description: From 11d83bffe6a5b29c655280950ebaa34767f3102a Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Aug 2023 21:25:33 +0200 Subject: [PATCH 154/365] Add "apn", remove "running" property for ppp-client interfaces (#202) Commit 2164261 added support for `interface ppp-client`. It missed the `apn` property and added the runtime-only `running` property. Signed-off-by: Michael Hanselmann --- plugins/module_utils/_api_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ee60e95..7ace4fc 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -304,6 +304,7 @@ PATHS = { fields={ 'add-default-route': KeyInfo(default=True), 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'apn': KeyInfo(default='internet'), 'comment': KeyInfo(can_disable=True, remove_value=''), 'data-channel': KeyInfo(default=0), 'default-route-distance': KeyInfo(default=1), @@ -323,7 +324,6 @@ PATHS = { 'pin': KeyInfo(default=''), 'port': KeyInfo(), 'profile': KeyInfo(default='default'), - 'running': KeyInfo(default=False), 'use-peer-dns': KeyInfo(default=True), 'user': KeyInfo(default=''), }, From adff9bbf8c58563b92be20f0e462acc098cad8bb Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 21 Aug 2023 21:32:43 +0200 Subject: [PATCH 155/365] Finalize fields for "interface wireless security-profiles" (#203) A few fields were missing for `interface wireless security-profiles` (e.g. `disabled`). `default` on the other hand is a built-in property which can't be modified. Mark the `interface wireless security-profiles` path as fully understood to enable its use in Ansible tasks. Signed-off-by: Michael Hanselmann --- .../203-wireless-security-profiles.yml | 2 + plugins/module_utils/_api_data.py | 46 +++++++++---------- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 changelogs/fragments/203-wireless-security-profiles.yml diff --git a/changelogs/fragments/203-wireless-security-profiles.yml b/changelogs/fragments/203-wireless-security-profiles.yml new file mode 100644 index 0000000..5eee689 --- /dev/null +++ b/changelogs/fragments/203-wireless-security-profiles.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 7ace4fc..2317b14 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1356,42 +1356,42 @@ PATHS = { }, ), ('interface', 'wireless', 'security-profiles'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), 'authentication-types': KeyInfo(), - 'disable-pmkid': KeyInfo(), + 'disable-pmkid': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), 'eap-methods': KeyInfo(), 'group-ciphers': KeyInfo(), - 'group-key-update': KeyInfo(), + 'group-key-update': KeyInfo(default='5m'), 'interim-update': KeyInfo(), - 'management-protection': KeyInfo(), - 'management-protection-key': KeyInfo(), - 'mode': KeyInfo(), - 'mschapv2-password': KeyInfo(), - 'mschapv2-username': KeyInfo(), + 'management-protection': KeyInfo(default='disabled'), + 'management-protection-key': KeyInfo(default=''), + 'mode': KeyInfo(default='none'), + 'mschapv2-password': KeyInfo(default=''), + 'mschapv2-username': KeyInfo(default=''), 'name': KeyInfo(), 'radius-called-format': KeyInfo(), - 'radius-eap-accounting': KeyInfo(), - 'radius-mac-accounting': KeyInfo(), - 'radius-mac-authentication': KeyInfo(), - 'radius-mac-caching': KeyInfo(), - 'radius-mac-format': KeyInfo(), - 'radius-mac-mode': KeyInfo(), - 'static-algo-0': KeyInfo(), - 'static-algo-1': KeyInfo(), - 'static-algo-2': KeyInfo(), - 'static-algo-3': KeyInfo(), + 'radius-eap-accounting': KeyInfo(default=False), + 'radius-mac-accounting': KeyInfo(default=False), + 'radius-mac-authentication': KeyInfo(default=False), + 'radius-mac-caching': KeyInfo(default='disabled'), + 'radius-mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), + 'radius-mac-mode': KeyInfo(default='as-username'), + 'static-algo-0': KeyInfo(default='none'), + 'static-algo-1': KeyInfo(default='none'), + 'static-algo-2': KeyInfo(default='none'), + 'static-algo-3': KeyInfo(default='none'), 'static-key-0': KeyInfo(), 'static-key-1': KeyInfo(), 'static-key-2': KeyInfo(), 'static-key-3': KeyInfo(), - 'static-sta-private-algo': KeyInfo(), + 'static-sta-private-algo': KeyInfo(default='none'), 'static-sta-private-key': KeyInfo(), 'static-transmit-key': KeyInfo(), - 'supplicant-identity': KeyInfo(), - 'tls-certificate': KeyInfo(), + 'supplicant-identity': KeyInfo(default='MikroTik'), + 'tls-certificate': KeyInfo(default='none'), 'tls-mode': KeyInfo(), 'unicast-ciphers': KeyInfo(), 'wpa-pre-shared-key': KeyInfo(), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 9947103..0aa2702 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -83,6 +83,7 @@ options: - interface wireless - interface wireless align - interface wireless cap + - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper - ip accounting diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 2fc7c57..9965502 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -88,6 +88,7 @@ options: - interface wireless - interface wireless align - interface wireless cap + - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper - ip accounting From b7569b9dfd373f862a0f96da3749151cf45827db Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 26 Aug 2023 11:23:00 +0200 Subject: [PATCH 156/365] Add support for "ipv6 firewall nat" (#204) RouterOS supports NAT for IPv6 under the `ipv6 firewall nat` path. Signed-off-by: Michael Hanselmann --- .../fragments/204-add-ipv6-firewall-nat.yml | 2 + plugins/module_utils/_api_data.py | 60 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 64 insertions(+) create mode 100644 changelogs/fragments/204-add-ipv6-firewall-nat.yml diff --git a/changelogs/fragments/204-add-ipv6-firewall-nat.yml b/changelogs/fragments/204-add-ipv6-firewall-nat.yml new file mode 100644 index 0000000..b61ef39 --- /dev/null +++ b/changelogs/fragments/204-add-ipv6-firewall-nat.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 2317b14..2a6f3f2 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2228,6 +2228,66 @@ PATHS = { 'tls-host': KeyInfo(can_disable=True), } ), + ('ipv6', 'firewall', 'nat'): APIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'to-addresses': KeyInfo(can_disable=True), + 'to-ports': KeyInfo(can_disable=True), + }, + ), ('ipv6', 'firewall', 'raw'): APIData( fully_understood=True, stratify_keys=('chain',), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 0aa2702..11e3fb6 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -137,6 +137,7 @@ options: - ipv6 firewall address-list - ipv6 firewall filter - ipv6 firewall mangle + - ipv6 firewall nat - ipv6 firewall raw - ipv6 nd - ipv6 nd prefix default diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 9965502..0b50437 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -142,6 +142,7 @@ options: - ipv6 firewall address-list - ipv6 firewall filter - ipv6 firewall mangle + - ipv6 firewall nat - ipv6 firewall raw - ipv6 nd - ipv6 nd prefix default From 193218446a3b0ff38f1403f3343f73f77b75af0c Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 26 Aug 2023 11:23:14 +0200 Subject: [PATCH 157/365] Add support for "iot modbus" (#205) The default values match those of RouterOS 7.11 on a Mikrotik RB924i-2nD-BT5&BG77 ("Knot"). Upstream documentation: https://help.mikrotik.com/docs/pages/viewpage.action?pageId=61046813 Signed-off-by: Michael Hanselmann --- changelogs/fragments/205-add-iot-modbus.yml | 2 ++ plugins/module_utils/_api_data.py | 10 ++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 14 insertions(+) create mode 100644 changelogs/fragments/205-add-iot-modbus.yml diff --git a/changelogs/fragments/205-add-iot-modbus.yml b/changelogs/fragments/205-add-iot-modbus.yml new file mode 100644 index 0000000..90a5875 --- /dev/null +++ b/changelogs/fragments/205-add-iot-modbus.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 2a6f3f2..28ff4e5 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1423,6 +1423,16 @@ PATHS = { 'receive-errors': KeyInfo(default=False), }, ), + ('iot', 'modbus'): APIData( + single_value=True, + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=True), + 'hardware-port': KeyInfo(default='modbus'), + 'tcp-port': KeyInfo(default=502), + 'timeout': KeyInfo(default=1000), + }, + ), ('ip', 'accounting'): APIData( single_value=True, fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 11e3fb6..165c0db 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -86,6 +86,7 @@ options: - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper + - iot modbus - ip accounting - ip accounting web-access - ip address diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 0b50437..8e6123a 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -91,6 +91,7 @@ options: - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper + - iot modbus - ip accounting - ip accounting web-access - ip address From 38ac303f933fa18cd6631f99b29488814f996e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Sztoch?= Date: Sat, 26 Aug 2023 11:49:20 +0200 Subject: [PATCH 158/365] Update ssh-guide.rst (#206) * Update ssh-guide.rst User is not allowed to login via SSH by password to Mikrotik if SSH key for the user is added! * Update previous note as it is no longer the last one. --------- Co-authored-by: Felix Fontein --- docs/docsite/rst/ssh-guide.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index f7297f9..7d907c7 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -31,7 +31,9 @@ Important notes 3. When using the :ref:`community.routeros.command module ` module, make sure to not specify too long commands. Alternatively, add something like ``+cet512w`` to the username (replace ``admin`` with ``admin+cet512w``) to tell RouterOS to not wrap before 512 characters in a line (`see issue for details `__). -4. Finally, the :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. +4. The :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. + +5. User is **not allowed** to login via SSH by password to modern Mikrotik if SSH key for the user is added! Setting up an inventory ----------------------- From 1ed469024028867c7876e178903b42b8fcef6d20 Mon Sep 17 00:00:00 2001 From: hansmi Date: Fri, 1 Sep 2023 22:02:11 +0200 Subject: [PATCH 159/365] Support "date", "time" and "gmt-offset" in "system clock" (#210) These properties are necessary to read and set the time as seen by RouterOS. Signed-off-by: Michael Hanselmann --- changelogs/fragments/210-date-time-gmt-offset.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/210-date-time-gmt-offset.yml diff --git a/changelogs/fragments/210-date-time-gmt-offset.yml b/changelogs/fragments/210-date-time-gmt-offset.yml new file mode 100644 index 0000000..7e3d114 --- /dev/null +++ b/changelogs/fragments/210-date-time-gmt-offset.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 28ff4e5..9eac5ec 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2551,6 +2551,9 @@ PATHS = { single_value=True, fully_understood=True, fields={ + 'date': KeyInfo(), + 'gmt-offset': KeyInfo(), + 'time': KeyInfo(), 'time-zone-autodetect': KeyInfo(default=True), 'time-zone-name': KeyInfo(default='manual'), }, From 4b0995135c6ab260b68ee46adb95e8da05c09f14 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 1 Sep 2023 22:27:18 +0200 Subject: [PATCH 160/365] Allow to differ on API paths based on RouterOS version (1/2) (#209) * Allow to provide definition for path based on API version. * The paths added in 343c4883c0a11a1f817ca6868c7d8550edc50944 are RouterOS 7+. --- plugins/module_utils/_api_data.py | 5783 +++++++++-------- plugins/module_utils/api.py | 7 + plugins/modules/api_info.py | 10 +- plugins/modules/api_modify.py | 26 +- .../plugins/module_utils/test__api_data.py | 22 +- tests/unit/plugins/modules/fake_api.py | 13 +- update-docs.py | 7 +- 7 files changed, 3158 insertions(+), 2710 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9eac5ec..867e51e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -9,8 +9,67 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +from ansible_collections.community.routeros.plugins.module_utils.version import LooseVersion + + +def _compare(a, b, comparator): + if comparator == '==': + return a == b + if comparator == '!=': + return a != b + if comparator == '<': + return a < b + if comparator == '<=': + return a <= b + if comparator == '>': + return a > b + if comparator == '>=': + return a >= b + raise ValueError('Unknown comparator "{comparator}"'.format(comparator=comparator)) + class APIData(object): + def __init__(self, + unversioned=None, + versioned=None): + if (unversioned is None) == (versioned is None): + raise ValueError('either unversioned or versioned must be provided') + self.unversioned = unversioned + self.versioned = versioned + if self.unversioned is not None: + self.needs_version = False + self.fully_understood = self.unversioned.fully_understood + else: + self.needs_version = self.versioned is not None + # Mark as 'fully understood' if it is for at least one version + self.fully_understood = False + for dummy, dummy, unversioned in self.versioned: + if unversioned.fully_understood: + self.fully_understood = True + break + + def provide_version(self, version): + if not self.needs_version: + return self.unversioned.fully_understood + api_version = LooseVersion(version) + for other_version, comparator, unversioned in self.versioned: + if other_version == '*' and comparator == '*': + self.unversioned = unversioned + return self.unversioned.fully_supported + other_api_version = LooseVersion(other_version) + if _compare(api_version, other_api_version, comparator): + self.unversioned = unversioned + return self.unversioned.fully_supported + self.unversioned = None + return False + + def get_data(self): + if self.unversioned is None: + raise ValueError('either provide_version() was not called or it returned False') + return self.unversioned + + +class VersionedAPIData(object): def __init__(self, primary_keys=None, stratify_keys=None, required_one_of=None, @@ -69,7 +128,7 @@ class KeyInfo(object): raise ValueError('KeyInfo() does not have positional arguments') if sum([required, default is not None or can_disable, automatically_computed_from is not None]) > 1: raise ValueError( - 'required, default, automatically_computed_from, and can_disable are mutually exclusive ' + + 'required, default, automatically_computed_from, and can_disable are mutually exclusive ' 'besides default and can_disable which can be set together') if not can_disable and remove_value is not None: raise ValueError('remove_value can only be specified if can_disable=True') @@ -99,3031 +158,3373 @@ def join_path(path): PATHS = { ('interface', 'bonding'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'arp': KeyInfo(default='enabled'), - 'arp-interval': KeyInfo(default='100ms'), - 'arp-ip-targets': KeyInfo(default=''), - 'arp-timeout': KeyInfo(default='auto'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'down-delay': KeyInfo(default='0ms'), - 'forced-mac-address': KeyInfo(can_disable=True), - 'lacp-rate': KeyInfo(default='30secs'), - 'lacp-user-key': KeyInfo(can_disable=True, remove_value=0), - 'link-monitoring': KeyInfo(default='mii'), - 'mii-interval': KeyInfo(default='100ms'), - 'min-links': KeyInfo(default=0), - 'mlag-id': KeyInfo(can_disable=True, remove_value=0), - 'mode': KeyInfo(default='balance-rr'), - 'mtu': KeyInfo(default=1500), - 'name': KeyInfo(), - 'primary': KeyInfo(default='none'), - 'slaves': KeyInfo(required=True), - 'transmit-hash-policy': KeyInfo(default='layer-2'), - 'up-delay': KeyInfo(default='0ms'), - } + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-interval': KeyInfo(default='100ms'), + 'arp-ip-targets': KeyInfo(default=''), + 'arp-timeout': KeyInfo(default='auto'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'down-delay': KeyInfo(default='0ms'), + 'forced-mac-address': KeyInfo(can_disable=True), + 'lacp-rate': KeyInfo(default='30secs'), + 'lacp-user-key': KeyInfo(can_disable=True, remove_value=0), + 'link-monitoring': KeyInfo(default='mii'), + 'mii-interval': KeyInfo(default='100ms'), + 'min-links': KeyInfo(default=0), + 'mlag-id': KeyInfo(can_disable=True, remove_value=0), + 'mode': KeyInfo(default='balance-rr'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'primary': KeyInfo(default='none'), + 'slaves': KeyInfo(required=True), + 'transmit-hash-policy': KeyInfo(default='layer-2'), + 'up-delay': KeyInfo(default='0ms'), + } + ), ), ('interface', 'bridge'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'admin-mac': KeyInfo(default=''), - 'ageing-time': KeyInfo(default='5m'), - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'auto-mac': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'dhcp-snooping': KeyInfo(default=False), - 'disabled': KeyInfo(default=False), - 'ether-type': KeyInfo(default='0x8100'), - 'fast-forward': KeyInfo(default=True), - 'frame-types': KeyInfo(default='admit-all'), - 'forward-delay': KeyInfo(default='15s'), - 'igmp-snooping': KeyInfo(default=False), - 'ingress-filtering': KeyInfo(default=True), - 'max-message-age': KeyInfo(default='20s'), - 'mtu': KeyInfo(default='auto'), - 'name': KeyInfo(), - 'priority': KeyInfo(default='0x8000'), - 'protocol-mode': KeyInfo(default='rstp'), - 'pvid': KeyInfo(default=1), - 'transmit-hold-count': KeyInfo(default=6), - 'vlan-filtering': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'admin-mac': KeyInfo(default=''), + 'ageing-time': KeyInfo(default='5m'), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'auto-mac': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-snooping': KeyInfo(default=False), + 'disabled': KeyInfo(default=False), + 'ether-type': KeyInfo(default='0x8100'), + 'fast-forward': KeyInfo(default=True), + 'frame-types': KeyInfo(default='admit-all'), + 'forward-delay': KeyInfo(default='15s'), + 'igmp-snooping': KeyInfo(default=False), + 'ingress-filtering': KeyInfo(default=True), + 'max-message-age': KeyInfo(default='20s'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'priority': KeyInfo(default='0x8000'), + 'protocol-mode': KeyInfo(default='rstp'), + 'pvid': KeyInfo(default=1), + 'transmit-hold-count': KeyInfo(default=6), + 'vlan-filtering': KeyInfo(default=False), + }, + ), ), ('interface', 'eoip'): APIData( - fully_understood=True, - primary_keys=('name',), - fields={ - 'allow-fast-path': KeyInfo(default=True), - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'clamp-tcp-mss': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'dont-fragment': KeyInfo(default=False), - 'dscp': KeyInfo(default='inherit'), - 'ipsec-secret': KeyInfo(can_disable=True), - 'keepalive': KeyInfo(default='10s,10', can_disable=True), - 'local-address': KeyInfo(default='0.0.0.0'), - 'loop-protect': KeyInfo(default='default'), - 'loop-protect-disable-time': KeyInfo(default='5m'), - 'loop-protect-send-interval': KeyInfo(default='5s'), - 'mac-address': KeyInfo(), - 'mtu': KeyInfo(default='auto'), - 'name': KeyInfo(), - 'remote-address': KeyInfo(required=True), - 'tunnel-id': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dont-fragment': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='0.0.0.0'), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mac-address': KeyInfo(), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + 'tunnel-id': KeyInfo(required=True), + }, + ), ), ('interface', 'ethernet'): APIData( - fixed_entries=True, - fully_understood=True, - primary_keys=('default-name', ), - fields={ - 'default-name': KeyInfo(), - 'advertise': KeyInfo(), - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'auto-negotiation': KeyInfo(default=True), - 'bandwidth': KeyInfo(default='unlimited/unlimited'), - 'combo-mode': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'fec-mode': KeyInfo(can_disable=True), - 'full-duplex': KeyInfo(default=True), - 'l2mtu': KeyInfo(default=1598), - 'loop-protect': KeyInfo(default='default'), - 'loop-protect-disable-time': KeyInfo(default='5m'), - 'loop-protect-send-interval': KeyInfo(default='5s'), - 'mac-address': KeyInfo(), - 'mdix-enable': KeyInfo(), - 'mtu': KeyInfo(default=1500), - 'name': KeyInfo(), - 'orig-mac-address': KeyInfo(), - 'poe-out': KeyInfo(can_disable=True), - 'poe-priority': KeyInfo(can_disable=True), - 'poe-voltage': KeyInfo(can_disable=True), - 'power-cycle-interval': KeyInfo(), - 'power-cycle-ping-address': KeyInfo(can_disable=True), - 'power-cycle-ping-enabled': KeyInfo(), - 'power-cycle-ping-timeout': KeyInfo(can_disable=True), - 'rx-flow-control': KeyInfo(default='off'), - 'sfp-rate-select': KeyInfo(default='high'), - 'sfp-shutdown-temperature': KeyInfo(default='95C'), - 'speed': KeyInfo(), - 'tx-flow-control': KeyInfo(default='off'), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + fully_understood=True, + primary_keys=('default-name', ), + fields={ + 'default-name': KeyInfo(), + 'advertise': KeyInfo(), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'auto-negotiation': KeyInfo(default=True), + 'bandwidth': KeyInfo(default='unlimited/unlimited'), + 'combo-mode': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'fec-mode': KeyInfo(can_disable=True), + 'full-duplex': KeyInfo(default=True), + 'l2mtu': KeyInfo(default=1598), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mac-address': KeyInfo(), + 'mdix-enable': KeyInfo(), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'orig-mac-address': KeyInfo(), + 'poe-out': KeyInfo(can_disable=True), + 'poe-priority': KeyInfo(can_disable=True), + 'poe-voltage': KeyInfo(can_disable=True), + 'power-cycle-interval': KeyInfo(), + 'power-cycle-ping-address': KeyInfo(can_disable=True), + 'power-cycle-ping-enabled': KeyInfo(), + 'power-cycle-ping-timeout': KeyInfo(can_disable=True), + 'rx-flow-control': KeyInfo(default='off'), + 'sfp-rate-select': KeyInfo(default='high'), + 'sfp-shutdown-temperature': KeyInfo(default='95C'), + 'speed': KeyInfo(), + 'tx-flow-control': KeyInfo(default='off'), + }, + ), ), ('interface', 'ethernet', 'poe'): APIData( - fixed_entries=True, - fully_understood=True, - primary_keys=('name', ), - fields={ - 'name': KeyInfo(), - 'poe-out': KeyInfo(default='auto-on'), - 'poe-priority': KeyInfo(default=10), - 'poe-voltage': KeyInfo(default='auto'), - 'power-cycle-interval': KeyInfo(default='none'), - 'power-cycle-ping-address': KeyInfo(can_disable=True), - 'power-cycle-ping-enabled': KeyInfo(default=False), - 'power-cycle-ping-timeout': KeyInfo(can_disable=True), - } + unversioned=VersionedAPIData( + fixed_entries=True, + fully_understood=True, + primary_keys=('name', ), + fields={ + 'name': KeyInfo(), + 'poe-out': KeyInfo(default='auto-on'), + 'poe-priority': KeyInfo(default=10), + 'poe-voltage': KeyInfo(default='auto'), + 'power-cycle-interval': KeyInfo(default='none'), + 'power-cycle-ping-address': KeyInfo(can_disable=True), + 'power-cycle-ping-enabled': KeyInfo(default=False), + 'power-cycle-ping-timeout': KeyInfo(can_disable=True), + } + ), ), ('interface', 'gre'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'allow-fast-path': KeyInfo(default=True), - 'clamp-tcp-mss': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'dont-fragment': KeyInfo(default=False), - 'dscp': KeyInfo(default='inherit'), - 'ipsec-secret': KeyInfo(can_disable=True), - 'keepalive': KeyInfo(default='10s,10', can_disable=True), - 'local-address': KeyInfo(default='0.0.0.0'), - 'mtu': KeyInfo(default='auto'), - 'name': KeyInfo(), - 'remote-address': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dont-fragment': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='0.0.0.0'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + }, + ), ), ('interface', 'gre6'): APIData( - fully_understood=True, - primary_keys=('name',), - fields={ - 'clamp-tcp-mss': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'dscp': KeyInfo(default='inherit'), - 'ipsec-secret': KeyInfo(can_disable=True), - 'keepalive': KeyInfo(default='10s,10', can_disable=True), - 'local-address': KeyInfo(default='::'), - 'mtu': KeyInfo(default='auto'), - 'name': KeyInfo(), - 'remote-address': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='::'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + }, + ), ), ('interface', 'list'): APIData( - primary_keys=('name', ), - fully_understood=True, - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'exclude': KeyInfo(), - 'include': KeyInfo(), - 'name': KeyInfo(), - }, + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'exclude': KeyInfo(), + 'include': KeyInfo(), + 'name': KeyInfo(), + }, + ), ), ('interface', 'list', 'member'): APIData( - primary_keys=('list', 'interface', ), - fully_understood=True, - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'interface': KeyInfo(), - 'list': KeyInfo(), - 'disabled': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + primary_keys=('list', 'interface', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'interface': KeyInfo(), + 'list': KeyInfo(), + 'disabled': KeyInfo(default=False), + }, + ), ), ('interface', 'lte', 'apn'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'add-default-route': KeyInfo(), - 'apn': KeyInfo(), - 'default-route-distance': KeyInfo(), - 'name': KeyInfo(), - 'use-peer-dns': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'add-default-route': KeyInfo(), + 'apn': KeyInfo(), + 'default-route-distance': KeyInfo(), + 'name': KeyInfo(), + 'use-peer-dns': KeyInfo(), + }, + ), ), ('interface', 'ppp-client'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'add-default-route': KeyInfo(default=True), - 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), - 'apn': KeyInfo(default='internet'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'data-channel': KeyInfo(default=0), - 'default-route-distance': KeyInfo(default=1), - 'dial-command': KeyInfo(default="ATDT"), - 'dial-on-demand': KeyInfo(default=True), - 'disabled': KeyInfo(default=True), - 'info-channel': KeyInfo(default=0), - 'keepalive-timeout': KeyInfo(default=30), - 'max-mru': KeyInfo(default=1500), - 'max-mtu': KeyInfo(default=1500), - 'modem-init': KeyInfo(default=''), - 'mrru': KeyInfo(default='disabled'), - 'name': KeyInfo(), - 'null-modem': KeyInfo(default=False), - 'password': KeyInfo(default=''), - 'phone': KeyInfo(default=''), - 'pin': KeyInfo(default=''), - 'port': KeyInfo(), - 'profile': KeyInfo(default='default'), - 'use-peer-dns': KeyInfo(default=True), - 'user': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'add-default-route': KeyInfo(default=True), + 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'apn': KeyInfo(default='internet'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'data-channel': KeyInfo(default=0), + 'default-route-distance': KeyInfo(default=1), + 'dial-command': KeyInfo(default="ATDT"), + 'dial-on-demand': KeyInfo(default=True), + 'disabled': KeyInfo(default=True), + 'info-channel': KeyInfo(default=0), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1500), + 'max-mtu': KeyInfo(default=1500), + 'modem-init': KeyInfo(default=''), + 'mrru': KeyInfo(default='disabled'), + 'name': KeyInfo(), + 'null-modem': KeyInfo(default=False), + 'password': KeyInfo(default=''), + 'phone': KeyInfo(default=''), + 'pin': KeyInfo(default=''), + 'port': KeyInfo(), + 'profile': KeyInfo(default='default'), + 'use-peer-dns': KeyInfo(default=True), + 'user': KeyInfo(default=''), + }, + ), ), ('interface', 'pppoe-client'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'ac-name': KeyInfo(default=''), - 'add-default-route': KeyInfo(default=False), - 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'default-route-distance': KeyInfo(default=1), - 'dial-on-demand': KeyInfo(default=False), - 'disabled': KeyInfo(default=True), - 'host-uniq': KeyInfo(can_disable=True), - 'interface': KeyInfo(required=True), - 'keepalive-timeout': KeyInfo(default=10), - 'max-mru': KeyInfo(default='auto'), - 'max-mtu': KeyInfo(default='auto'), - 'mrru': KeyInfo(default='disabled'), - 'name': KeyInfo(), - 'password': KeyInfo(default=''), - 'profile': KeyInfo(default='default'), - 'service-name': KeyInfo(default=''), - 'use-peer-dns': KeyInfo(default=False), - 'user': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'ac-name': KeyInfo(default=''), + 'add-default-route': KeyInfo(default=False), + 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dial-on-demand': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'host-uniq': KeyInfo(can_disable=True), + 'interface': KeyInfo(required=True), + 'keepalive-timeout': KeyInfo(default=10), + 'max-mru': KeyInfo(default='auto'), + 'max-mtu': KeyInfo(default='auto'), + 'mrru': KeyInfo(default='disabled'), + 'name': KeyInfo(), + 'password': KeyInfo(default=''), + 'profile': KeyInfo(default='default'), + 'service-name': KeyInfo(default=''), + 'use-peer-dns': KeyInfo(default=False), + 'user': KeyInfo(default=''), + }, + ), ), ('interface', 'vlan'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interface': KeyInfo(required=True), - 'loop-protect': KeyInfo(default='default'), - 'loop-protect-disable-time': KeyInfo(default='5m'), - 'loop-protect-send-interval': KeyInfo(default='5s'), - 'mtu': KeyInfo(default=1500), - 'name': KeyInfo(), - 'use-service-tag': KeyInfo(default=False), - 'vlan-id': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'loop-protect': KeyInfo(default='default'), + 'loop-protect-disable-time': KeyInfo(default='5m'), + 'loop-protect-send-interval': KeyInfo(default='5s'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'use-service-tag': KeyInfo(default=False), + 'vlan-id': KeyInfo(required=True), + }, + ), ), ('interface', 'vrrp'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'authentication': KeyInfo(default='none'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'group-master': KeyInfo(default=''), - 'interface': KeyInfo(required=True), - 'interval': KeyInfo(default='1s'), - 'mtu': KeyInfo(default=1500), - 'name': KeyInfo(), - 'on-backup': KeyInfo(default=''), - 'on-fail': KeyInfo(default=''), - 'on-master': KeyInfo(default=''), - 'password': KeyInfo(default=''), - 'preemption-mode': KeyInfo(default=True), - 'priority': KeyInfo(default=100), - 'remote-address': KeyInfo(), - 'sync-connection-tracking': KeyInfo(default=False), - 'v3-protocol': KeyInfo(default='ipv4'), - 'version': KeyInfo(default=3), - 'vrid': KeyInfo(default=1), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'authentication': KeyInfo(default='none'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'group-master': KeyInfo(default=''), + 'interface': KeyInfo(required=True), + 'interval': KeyInfo(default='1s'), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'on-backup': KeyInfo(default=''), + 'on-fail': KeyInfo(default=''), + 'on-master': KeyInfo(default=''), + 'password': KeyInfo(default=''), + 'preemption-mode': KeyInfo(default=True), + 'priority': KeyInfo(default=100), + 'remote-address': KeyInfo(), + 'sync-connection-tracking': KeyInfo(default=False), + 'v3-protocol': KeyInfo(default='ipv4'), + 'version': KeyInfo(default=3), + 'vrid': KeyInfo(default=1), + }, + ), ), ('ip', 'hotspot', 'profile'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'dns-name': KeyInfo(), - 'hotspot-address': KeyInfo(), - 'html-directory': KeyInfo(), - 'html-directory-override': KeyInfo(), - 'http-cookie-lifetime': KeyInfo(), - 'http-proxy': KeyInfo(), - 'login-by': KeyInfo(), - 'name': KeyInfo(), - 'rate-limit': KeyInfo(), - 'smtp-server': KeyInfo(), - 'split-user-domain': KeyInfo(), - 'use-radius': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'dns-name': KeyInfo(), + 'hotspot-address': KeyInfo(), + 'html-directory': KeyInfo(), + 'html-directory-override': KeyInfo(), + 'http-cookie-lifetime': KeyInfo(), + 'http-proxy': KeyInfo(), + 'login-by': KeyInfo(), + 'name': KeyInfo(), + 'rate-limit': KeyInfo(), + 'smtp-server': KeyInfo(), + 'split-user-domain': KeyInfo(), + 'use-radius': KeyInfo(), + }, + ), ), ('ip', 'hotspot', 'user', 'profile'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'add-mac-cookie': KeyInfo(), - 'address-list': KeyInfo(), - 'idle-timeout': KeyInfo(), - 'insert-queue-before': KeyInfo(can_disable=True), - 'keepalive-timeout': KeyInfo(), - 'mac-cookie-timeout': KeyInfo(), - 'name': KeyInfo(), - 'parent-queue': KeyInfo(can_disable=True), - 'queue-type': KeyInfo(can_disable=True), - 'shared-users': KeyInfo(), - 'status-autorefresh': KeyInfo(), - 'transparent-proxy': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'add-mac-cookie': KeyInfo(), + 'address-list': KeyInfo(), + 'idle-timeout': KeyInfo(), + 'insert-queue-before': KeyInfo(can_disable=True), + 'keepalive-timeout': KeyInfo(), + 'mac-cookie-timeout': KeyInfo(), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True), + 'queue-type': KeyInfo(can_disable=True), + 'shared-users': KeyInfo(), + 'status-autorefresh': KeyInfo(), + 'transparent-proxy': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'identity'): APIData( - fully_understood=True, - primary_keys=('peer', ), - fields={ - 'auth-method': KeyInfo(default='pre-shared-key'), - 'certificate': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'eap-methods': KeyInfo(default='eap-tls'), - 'generate-policy': KeyInfo(default=False), - 'key': KeyInfo(), - 'match-by': KeyInfo(can_disable=True, remove_value='remote-id'), - 'mode-config': KeyInfo(can_disable=True, remove_value='none'), - 'my-id': KeyInfo(can_disable=True, remove_value='auto'), - 'notrack-chain': KeyInfo(can_disable=True, remove_value=''), - 'password': KeyInfo(), - 'peer': KeyInfo(), - 'policy-template-group': KeyInfo(can_disable=True, remove_value='default'), - 'remote-certificate': KeyInfo(), - 'remote-id': KeyInfo(can_disable=True, remove_value='auto'), - 'remote-key': KeyInfo(), - 'secret': KeyInfo(default=''), - 'username': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('peer', ), + fields={ + 'auth-method': KeyInfo(default='pre-shared-key'), + 'certificate': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'eap-methods': KeyInfo(default='eap-tls'), + 'generate-policy': KeyInfo(default=False), + 'key': KeyInfo(), + 'match-by': KeyInfo(can_disable=True, remove_value='remote-id'), + 'mode-config': KeyInfo(can_disable=True, remove_value='none'), + 'my-id': KeyInfo(can_disable=True, remove_value='auto'), + 'notrack-chain': KeyInfo(can_disable=True, remove_value=''), + 'password': KeyInfo(), + 'peer': KeyInfo(), + 'policy-template-group': KeyInfo(can_disable=True, remove_value='default'), + 'remote-certificate': KeyInfo(), + 'remote-id': KeyInfo(can_disable=True, remove_value='auto'), + 'remote-key': KeyInfo(), + 'secret': KeyInfo(default=''), + 'username': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'mode-config'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'name': KeyInfo(), - 'responder': KeyInfo(), - 'use-responder-dns': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'name': KeyInfo(), + 'responder': KeyInfo(), + 'use-responder-dns': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'peer'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'address': KeyInfo(can_disable=True, remove_value=''), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'exchange-mode': KeyInfo(default='main'), - 'local-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), - 'name': KeyInfo(), - 'passive': KeyInfo(can_disable=True, remove_value=False), - 'port': KeyInfo(can_disable=True, remove_value=500), - 'profile': KeyInfo(default='default'), - 'send-initial-contact': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'exchange-mode': KeyInfo(default='main'), + 'local-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'name': KeyInfo(), + 'passive': KeyInfo(can_disable=True, remove_value=False), + 'port': KeyInfo(can_disable=True, remove_value=500), + 'profile': KeyInfo(default='default'), + 'send-initial-contact': KeyInfo(default=True), + }, + ), ), ('ip', 'ipsec', 'policy', 'group'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'name': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'name': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'profile'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'dh-group': KeyInfo(default='modp2048,modp1024'), - 'dpd-interval': KeyInfo(default='2m'), - 'dpd-maximum-failures': KeyInfo(default=5), - 'enc-algorithm': KeyInfo(default='aes-128,3des'), - 'hash-algorithm': KeyInfo(default='sha1'), - 'lifebytes': KeyInfo(can_disable=True, remove_value=0), - 'lifetime': KeyInfo(default='1d'), - 'name': KeyInfo(), - 'nat-traversal': KeyInfo(default=True), - 'prf-algorithm': KeyInfo(can_disable=True, remove_value='auto'), - 'proposal-check': KeyInfo(default='obey'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'dh-group': KeyInfo(default='modp2048,modp1024'), + 'dpd-interval': KeyInfo(default='2m'), + 'dpd-maximum-failures': KeyInfo(default=5), + 'enc-algorithm': KeyInfo(default='aes-128,3des'), + 'hash-algorithm': KeyInfo(default='sha1'), + 'lifebytes': KeyInfo(can_disable=True, remove_value=0), + 'lifetime': KeyInfo(default='1d'), + 'name': KeyInfo(), + 'nat-traversal': KeyInfo(default=True), + 'prf-algorithm': KeyInfo(can_disable=True, remove_value='auto'), + 'proposal-check': KeyInfo(default='obey'), + }, + ), ), ('ip', 'ipsec', 'proposal'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'auth-algorithms': KeyInfo(default='sha1'), - 'disabled': KeyInfo(default=False), - 'enc-algorithms': KeyInfo(default='aes-256-cbc,aes-192-cbc,aes-128-cbc'), - 'lifetime': KeyInfo(default='30m'), - 'name': KeyInfo(), - 'pfs-group': KeyInfo(default='modp1024'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'auth-algorithms': KeyInfo(default='sha1'), + 'disabled': KeyInfo(default=False), + 'enc-algorithms': KeyInfo(default='aes-256-cbc,aes-192-cbc,aes-128-cbc'), + 'lifetime': KeyInfo(default='30m'), + 'name': KeyInfo(), + 'pfs-group': KeyInfo(default='modp1024'), + }, + ), ), ('ip', 'pool'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'name': KeyInfo(), - 'ranges': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'name': KeyInfo(), + 'ranges': KeyInfo(), + }, + ), ), ('ip', 'route'): APIData( - fully_understood=True, - fields={ - 'blackhole': KeyInfo(can_disable=True), - 'check-gateway': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'distance': KeyInfo(), - 'dst-address': KeyInfo(), - 'gateway': KeyInfo(), - 'pref-src': KeyInfo(), - 'routing-table': KeyInfo(default='main'), - 'route-tag': KeyInfo(can_disable=True), - 'routing-mark': KeyInfo(can_disable=True), - 'scope': KeyInfo(), - 'suppress-hw-offload': KeyInfo(default=False), - 'target-scope': KeyInfo(), - 'type': KeyInfo(can_disable=True, remove_value='unicast'), - 'vrf-interface': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'blackhole': KeyInfo(can_disable=True), + 'check-gateway': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'distance': KeyInfo(), + 'dst-address': KeyInfo(), + 'gateway': KeyInfo(), + 'pref-src': KeyInfo(), + 'routing-table': KeyInfo(default='main'), + 'route-tag': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'scope': KeyInfo(), + 'suppress-hw-offload': KeyInfo(default=False), + 'target-scope': KeyInfo(), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'vrf-interface': KeyInfo(can_disable=True), + }, + ), ), ('ip', 'route', 'vrf'): APIData( - fully_understood=True, - primary_keys=('routing-mark', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interfaces': KeyInfo(), - 'routing-mark': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('routing-mark', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interfaces': KeyInfo(), + 'routing-mark': KeyInfo(), + }, + ), ), ('ip', 'dhcp-server'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'address-pool': KeyInfo(default='static-only'), - 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), - 'always-broadcast': KeyInfo(can_disable=True, remove_value=False), - 'authoritative': KeyInfo(default=True), - 'bootp-lease-time': KeyInfo(default='forever'), - 'bootp-support': KeyInfo(can_disable=True, remove_value='static'), - 'client-mac-limit': KeyInfo(can_disable=True, remove_value='unlimited'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'conflict-detection': KeyInfo(can_disable=True, remove_value=True), - 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), - 'dhcp-option-set': KeyInfo(can_disable=True, remove_value='none'), - 'disabled': KeyInfo(default=False), - 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), - 'interface': KeyInfo(required=True), - 'lease-script': KeyInfo(default=''), - 'lease-time': KeyInfo(default='10m'), - 'name': KeyInfo(), - 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), - 'relay': KeyInfo(can_disable=True, remove_value='0.0.0.0'), - 'server-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), - 'use-framed-as-classless': KeyInfo(can_disable=True, remove_value=True), - 'use-radius': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(default='static-only'), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'always-broadcast': KeyInfo(can_disable=True, remove_value=False), + 'authoritative': KeyInfo(default=True), + 'bootp-lease-time': KeyInfo(default='forever'), + 'bootp-support': KeyInfo(can_disable=True, remove_value='static'), + 'client-mac-limit': KeyInfo(can_disable=True, remove_value='unlimited'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'conflict-detection': KeyInfo(can_disable=True, remove_value=True), + 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), + 'dhcp-option-set': KeyInfo(can_disable=True, remove_value='none'), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), + 'interface': KeyInfo(required=True), + 'lease-script': KeyInfo(default=''), + 'lease-time': KeyInfo(default='10m'), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'relay': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'server-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'use-framed-as-classless': KeyInfo(can_disable=True, remove_value=True), + 'use-radius': KeyInfo(default=False), + }, + ), ), ('routing', 'filter', 'rule'): APIData( - fully_understood=True, - fields={ - 'chain': KeyInfo(required=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(can_disable=True), - 'rule': KeyInfo(can_disable=True), - }, + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'chain': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'rule': KeyInfo(can_disable=True), + }, + )), + ], ), ('routing', 'filter', 'select-rule'): APIData( - fully_understood=True, - fields={ - 'chain': KeyInfo(required=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(can_disable=True), - 'do-group-num': KeyInfo(can_disable=True), - 'do-group-prfx': KeyInfo(can_disable=True), - 'do-jump': KeyInfo(can_disable=True), - 'do-select-num': KeyInfo(can_disable=True), - 'do-select-prfx': KeyInfo(can_disable=True), - 'do-take': KeyInfo(can_disable=True), - 'do-where': KeyInfo(can_disable=True), - }, + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'chain': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'do-group-num': KeyInfo(can_disable=True), + 'do-group-prfx': KeyInfo(can_disable=True), + 'do-jump': KeyInfo(can_disable=True), + 'do-select-num': KeyInfo(can_disable=True), + 'do-select-prfx': KeyInfo(can_disable=True), + 'do-take': KeyInfo(can_disable=True), + 'do-where': KeyInfo(can_disable=True), + }, + )), + ], ), ('routing', 'ospf', 'instance'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'domain-id': KeyInfo(can_disable=True), - 'domain-tag': KeyInfo(can_disable=True), - 'in-filter-chain': KeyInfo(can_disable=True), - 'mpls-te-address': KeyInfo(can_disable=True), - 'mpls-te-area': KeyInfo(can_disable=True), - 'name': KeyInfo(), - 'originate-default': KeyInfo(can_disable=True), - 'out-filter-chain': KeyInfo(can_disable=True), - 'out-filter-select': KeyInfo(can_disable=True), - 'redistribute': KeyInfo(can_disable=True), - 'router-id': KeyInfo(default='main'), - 'routing-table': KeyInfo(can_disable=True), - 'use-dn': KeyInfo(can_disable=True), - 'version': KeyInfo(default=2), - 'vrf': KeyInfo(default='main'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'domain-id': KeyInfo(can_disable=True), + 'domain-tag': KeyInfo(can_disable=True), + 'in-filter-chain': KeyInfo(can_disable=True), + 'mpls-te-address': KeyInfo(can_disable=True), + 'mpls-te-area': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'originate-default': KeyInfo(can_disable=True), + 'out-filter-chain': KeyInfo(can_disable=True), + 'out-filter-select': KeyInfo(can_disable=True), + 'redistribute': KeyInfo(can_disable=True), + 'router-id': KeyInfo(default='main'), + 'routing-table': KeyInfo(can_disable=True), + 'use-dn': KeyInfo(can_disable=True), + 'version': KeyInfo(default=2), + 'vrf': KeyInfo(default='main'), + }, + ), ), ('routing', 'ospf', 'area'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'area-id': KeyInfo(default='0.0.0.0'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'default-cost': KeyInfo(can_disable=True), - 'disabled': KeyInfo(default=False), - 'instance': KeyInfo(required=True), - 'name': KeyInfo(), - 'no-summaries': KeyInfo(can_disable=True), - 'nssa-translator': KeyInfo(can_disable=True), - 'type': KeyInfo(default='default'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'area-id': KeyInfo(default='0.0.0.0'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'instance': KeyInfo(required=True), + 'name': KeyInfo(), + 'no-summaries': KeyInfo(can_disable=True), + 'nssa-translator': KeyInfo(can_disable=True), + 'type': KeyInfo(default='default'), + }, + ), ), ('routing', 'ospf', 'area', 'range'): APIData( - fully_understood=True, - primary_keys=('area', 'prefix', ), - fields={ - 'advertise': KeyInfo(default=True), - 'area': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'cost': KeyInfo(can_disable=True), - 'disabled': KeyInfo(default=False), - 'prefix': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('area', 'prefix', ), + fields={ + 'advertise': KeyInfo(default=True), + 'area': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'prefix': KeyInfo(), + }, + ), ), ('routing', 'ospf', 'interface-template'): APIData( - fully_understood=True, - fields={ - 'area': KeyInfo(required=True), - 'auth': KeyInfo(can_disable=True), - 'auth-id': KeyInfo(can_disable=True), - 'auth-key': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'cost': KeyInfo(default=1), - 'dead-interval': KeyInfo(default='40s'), - 'disabled': KeyInfo(default=False), - 'hello-interval': KeyInfo(default='10s'), - 'instance-id': KeyInfo(default=0), - 'interfaces': KeyInfo(can_disable=True), - 'networks': KeyInfo(can_disable=True), - 'passive': KeyInfo(can_disable=True), - 'prefix-list': KeyInfo(can_disable=True), - 'priority': KeyInfo(default=128), - 'retransmit-interval': KeyInfo(default='5s'), - 'transmit-delay': KeyInfo(default='1s'), - 'type': KeyInfo(default='broadcast'), - 'vlink-neighbor-id': KeyInfo(can_disable=True), - 'vlink-transit-area': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'area': KeyInfo(required=True), + 'auth': KeyInfo(can_disable=True), + 'auth-id': KeyInfo(can_disable=True), + 'auth-key': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(default=1), + 'dead-interval': KeyInfo(default='40s'), + 'disabled': KeyInfo(default=False), + 'hello-interval': KeyInfo(default='10s'), + 'instance-id': KeyInfo(default=0), + 'interfaces': KeyInfo(can_disable=True), + 'networks': KeyInfo(can_disable=True), + 'passive': KeyInfo(can_disable=True), + 'prefix-list': KeyInfo(can_disable=True), + 'priority': KeyInfo(default=128), + 'retransmit-interval': KeyInfo(default='5s'), + 'transmit-delay': KeyInfo(default='1s'), + 'type': KeyInfo(default='broadcast'), + 'vlink-neighbor-id': KeyInfo(can_disable=True), + 'vlink-transit-area': KeyInfo(can_disable=True), + }, + ), ), ('routing', 'ospf-v3', 'instance'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'distribute-default': KeyInfo(), - 'metric-bgp': KeyInfo(), - 'metric-connected': KeyInfo(), - 'metric-default': KeyInfo(), - 'metric-other-ospf': KeyInfo(), - 'metric-rip': KeyInfo(), - 'metric-static': KeyInfo(), - 'name': KeyInfo(), - 'redistribute-bgp': KeyInfo(), - 'redistribute-connected': KeyInfo(), - 'redistribute-other-ospf': KeyInfo(), - 'redistribute-rip': KeyInfo(), - 'redistribute-static': KeyInfo(), - 'router-id': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'distribute-default': KeyInfo(), + 'metric-bgp': KeyInfo(), + 'metric-connected': KeyInfo(), + 'metric-default': KeyInfo(), + 'metric-other-ospf': KeyInfo(), + 'metric-rip': KeyInfo(), + 'metric-static': KeyInfo(), + 'name': KeyInfo(), + 'redistribute-bgp': KeyInfo(), + 'redistribute-connected': KeyInfo(), + 'redistribute-other-ospf': KeyInfo(), + 'redistribute-rip': KeyInfo(), + 'redistribute-static': KeyInfo(), + 'router-id': KeyInfo(), + }, + ), ), ('routing', 'ospf-v3', 'area'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'area-id': KeyInfo(), - 'disabled': KeyInfo(), - 'instance': KeyInfo(), - 'name': KeyInfo(), - 'type': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'area-id': KeyInfo(), + 'disabled': KeyInfo(), + 'instance': KeyInfo(), + 'name': KeyInfo(), + 'type': KeyInfo(), + }, + ), ), ('routing', 'pimsm', 'instance'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'afi': KeyInfo(default='ipv4'), - 'bsm-forward-back': KeyInfo(), - 'crp-advertise-contained': KeyInfo(), - 'disabled': KeyInfo(default=False), - 'name': KeyInfo(), - 'rp-hash-mask-length': KeyInfo(), - 'rp-static-override': KeyInfo(default=False), - 'ssm-range': KeyInfo(), - 'switch-to-spt': KeyInfo(default=True), - 'switch-to-spt-bytes': KeyInfo(default=0), - 'switch-to-spt-interval': KeyInfo(), - 'vrf': KeyInfo(default="main"), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'afi': KeyInfo(default='ipv4'), + 'bsm-forward-back': KeyInfo(), + 'crp-advertise-contained': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'rp-hash-mask-length': KeyInfo(), + 'rp-static-override': KeyInfo(default=False), + 'ssm-range': KeyInfo(), + 'switch-to-spt': KeyInfo(default=True), + 'switch-to-spt-bytes': KeyInfo(default=0), + 'switch-to-spt-interval': KeyInfo(), + 'vrf': KeyInfo(default="main"), + }, + ), ), ('routing', 'pimsm', 'interface-template'): APIData( - fully_understood=True, - fields={ - 'disabled': KeyInfo(default=False), - 'hello-delay': KeyInfo(default='5s'), - 'hello-period': KeyInfo(default='30s'), - 'instance': KeyInfo(required=True), - 'interfaces': KeyInfo(can_disable=True), - 'join-prune-period': KeyInfo(default='1m'), - 'join-tracking-support': KeyInfo(default=True), - 'override-interval': KeyInfo(default='2s500ms'), - 'priority': KeyInfo(default=1), - 'propagation-delay': KeyInfo(default='500ms'), - 'source-addresses': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'hello-delay': KeyInfo(default='5s'), + 'hello-period': KeyInfo(default='30s'), + 'instance': KeyInfo(required=True), + 'interfaces': KeyInfo(can_disable=True), + 'join-prune-period': KeyInfo(default='1m'), + 'join-tracking-support': KeyInfo(default=True), + 'override-interval': KeyInfo(default='2s500ms'), + 'priority': KeyInfo(default=1), + 'propagation-delay': KeyInfo(default='500ms'), + 'source-addresses': KeyInfo(can_disable=True), + }, + ), ), ('snmp', 'community'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'addresses': KeyInfo(default='::/0'), - 'authentication-password': KeyInfo(default=''), - 'authentication-protocol': KeyInfo(default='MD5'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'encryption-password': KeyInfo(default=''), - 'encryption-protocol': KeyInfo(default='DES'), - 'name': KeyInfo(required=True), - 'read-access': KeyInfo(default=True), - 'security': KeyInfo(default='none'), - 'write-access': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'addresses': KeyInfo(default='::/0'), + 'authentication-password': KeyInfo(default=''), + 'authentication-protocol': KeyInfo(default='MD5'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'encryption-password': KeyInfo(default=''), + 'encryption-protocol': KeyInfo(default='DES'), + 'name': KeyInfo(required=True), + 'read-access': KeyInfo(default=True), + 'security': KeyInfo(default='none'), + 'write-access': KeyInfo(default=False), + }, + ), ), ('caps-man', 'aaa'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'called-format': KeyInfo(default='mac:ssid'), - 'interim-update': KeyInfo(default='disabled'), - 'mac-caching': KeyInfo(default='disabled'), - 'mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), - 'mac-mode': KeyInfo(default='as-username'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'called-format': KeyInfo(default='mac:ssid'), + 'interim-update': KeyInfo(default='disabled'), + 'mac-caching': KeyInfo(default='disabled'), + 'mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), + 'mac-mode': KeyInfo(default='as-username'), + }, + ), ), ('caps-man', 'access-list'): APIData( - fully_understood=True, - fields={ - 'action': KeyInfo(can_disable=True), - 'allow-signal-out-of-range': KeyInfo(can_disable=True), - 'ap-tx-limit': KeyInfo(can_disable=True), - 'client-to-client-forwarding': KeyInfo(can_disable=True), - 'client-tx-limit': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(), - 'interface': KeyInfo(can_disable=True), - 'mac-address': KeyInfo(can_disable=True), - 'mac-address-mask': KeyInfo(can_disable=True), - 'private-passphrase': KeyInfo(can_disable=True), - 'radius-accounting': KeyInfo(can_disable=True), - 'signal-range': KeyInfo(can_disable=True), - 'ssid-regexp': KeyInfo(), - 'time': KeyInfo(can_disable=True), - 'vlan-id': KeyInfo(can_disable=True), - 'vlan-mode': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(can_disable=True), + 'allow-signal-out-of-range': KeyInfo(can_disable=True), + 'ap-tx-limit': KeyInfo(can_disable=True), + 'client-to-client-forwarding': KeyInfo(can_disable=True), + 'client-tx-limit': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(), + 'interface': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True), + 'mac-address-mask': KeyInfo(can_disable=True), + 'private-passphrase': KeyInfo(can_disable=True), + 'radius-accounting': KeyInfo(can_disable=True), + 'signal-range': KeyInfo(can_disable=True), + 'ssid-regexp': KeyInfo(), + 'time': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + 'vlan-mode': KeyInfo(can_disable=True), + }, + ), ), ('caps-man', 'channel'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'band': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'control-channel-width': KeyInfo(can_disable=True), - 'extension-channel': KeyInfo(can_disable=True), - 'frequency': KeyInfo(can_disable=True), - 'name': KeyInfo(), - 'reselect-interval': KeyInfo(can_disable=True), - 'save-selected': KeyInfo(can_disable=True), - 'secondary-frequency': KeyInfo(can_disable=True), - 'skip-dfs-channels': KeyInfo(can_disable=True), - 'tx-power': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'band': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'control-channel-width': KeyInfo(can_disable=True), + 'extension-channel': KeyInfo(can_disable=True), + 'frequency': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'reselect-interval': KeyInfo(can_disable=True), + 'save-selected': KeyInfo(can_disable=True), + 'secondary-frequency': KeyInfo(can_disable=True), + 'skip-dfs-channels': KeyInfo(can_disable=True), + 'tx-power': KeyInfo(can_disable=True), + }, + ), ), ('caps-man', 'configuration'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'channel': KeyInfo(can_disable=True), - 'channel.band': KeyInfo(can_disable=True), - 'channel.control-channel-width': KeyInfo(can_disable=True), - 'channel.extension-channel': KeyInfo(can_disable=True), - 'channel.frequency': KeyInfo(can_disable=True), - 'channel.reselect-interval': KeyInfo(can_disable=True), - 'channel.save-selected': KeyInfo(can_disable=True), - 'channel.secondary-frequency': KeyInfo(can_disable=True), - 'channel.skip-dfs-channels': KeyInfo(can_disable=True), - 'channel.tx-power': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'country': KeyInfo(can_disable=True), - 'datapath': KeyInfo(can_disable=True), - 'datapath.arp': KeyInfo(), - 'datapath.bridge': KeyInfo(can_disable=True), - 'datapath.bridge-cost': KeyInfo(can_disable=True), - 'datapath.bridge-horizon': KeyInfo(can_disable=True), - 'datapath.client-to-client-forwarding': KeyInfo(can_disable=True), - 'datapath.interface-list': KeyInfo(can_disable=True), - 'datapath.l2mtu': KeyInfo(), - 'datapath.local-forwarding': KeyInfo(can_disable=True), - 'datapath.mtu': KeyInfo(), - 'datapath.openflow-switch': KeyInfo(can_disable=True), - 'datapath.vlan-id': KeyInfo(can_disable=True), - 'datapath.vlan-mode': KeyInfo(can_disable=True), - 'disconnect-timeout': KeyInfo(can_disable=True), - 'distance': KeyInfo(can_disable=True), - 'frame-lifetime': KeyInfo(can_disable=True), - 'guard-interval': KeyInfo(can_disable=True), - 'hide-ssid': KeyInfo(can_disable=True), - 'hw-protection-mode': KeyInfo(can_disable=True), - 'hw-retries': KeyInfo(can_disable=True), - 'installation': KeyInfo(can_disable=True), - 'keepalive-frames': KeyInfo(can_disable=True), - 'load-balancing-group': KeyInfo(can_disable=True), - 'max-sta-count': KeyInfo(can_disable=True), - 'mode': KeyInfo(can_disable=True), - 'multicast-helper': KeyInfo(can_disable=True), - 'name': KeyInfo(), - 'rates': KeyInfo(can_disable=True), - 'rates.basic': KeyInfo(can_disable=True), - 'rates.ht-basic-mcs': KeyInfo(can_disable=True), - 'rates.ht-supported-mcs': KeyInfo(can_disable=True), - 'rates.supported': KeyInfo(can_disable=True), - 'rates.vht-basic-mcs': KeyInfo(can_disable=True), - 'rates.vht-supported-mcs': KeyInfo(can_disable=True), - 'rx-chains': KeyInfo(can_disable=True), - 'security': KeyInfo(can_disable=True), - 'security.authentication-types': KeyInfo(can_disable=True), - 'security.disable-pmkid': KeyInfo(can_disable=True), - 'security.eap-methods': KeyInfo(can_disable=True), - 'security.eap-radius-accounting': KeyInfo(can_disable=True), - 'security.encryption': KeyInfo(can_disable=True), - 'security.group-encryption': KeyInfo(can_disable=True), - 'security.group-key-update': KeyInfo(), - 'security.passphrase': KeyInfo(can_disable=True), - 'security.tls-certificate': KeyInfo(), - 'security.tls-mode': KeyInfo(), - 'ssid': KeyInfo(can_disable=True), - 'tx-chains': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'channel': KeyInfo(can_disable=True), + 'channel.band': KeyInfo(can_disable=True), + 'channel.control-channel-width': KeyInfo(can_disable=True), + 'channel.extension-channel': KeyInfo(can_disable=True), + 'channel.frequency': KeyInfo(can_disable=True), + 'channel.reselect-interval': KeyInfo(can_disable=True), + 'channel.save-selected': KeyInfo(can_disable=True), + 'channel.secondary-frequency': KeyInfo(can_disable=True), + 'channel.skip-dfs-channels': KeyInfo(can_disable=True), + 'channel.tx-power': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'country': KeyInfo(can_disable=True), + 'datapath': KeyInfo(can_disable=True), + 'datapath.arp': KeyInfo(), + 'datapath.bridge': KeyInfo(can_disable=True), + 'datapath.bridge-cost': KeyInfo(can_disable=True), + 'datapath.bridge-horizon': KeyInfo(can_disable=True), + 'datapath.client-to-client-forwarding': KeyInfo(can_disable=True), + 'datapath.interface-list': KeyInfo(can_disable=True), + 'datapath.l2mtu': KeyInfo(), + 'datapath.local-forwarding': KeyInfo(can_disable=True), + 'datapath.mtu': KeyInfo(), + 'datapath.openflow-switch': KeyInfo(can_disable=True), + 'datapath.vlan-id': KeyInfo(can_disable=True), + 'datapath.vlan-mode': KeyInfo(can_disable=True), + 'disconnect-timeout': KeyInfo(can_disable=True), + 'distance': KeyInfo(can_disable=True), + 'frame-lifetime': KeyInfo(can_disable=True), + 'guard-interval': KeyInfo(can_disable=True), + 'hide-ssid': KeyInfo(can_disable=True), + 'hw-protection-mode': KeyInfo(can_disable=True), + 'hw-retries': KeyInfo(can_disable=True), + 'installation': KeyInfo(can_disable=True), + 'keepalive-frames': KeyInfo(can_disable=True), + 'load-balancing-group': KeyInfo(can_disable=True), + 'max-sta-count': KeyInfo(can_disable=True), + 'mode': KeyInfo(can_disable=True), + 'multicast-helper': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'rates': KeyInfo(can_disable=True), + 'rates.basic': KeyInfo(can_disable=True), + 'rates.ht-basic-mcs': KeyInfo(can_disable=True), + 'rates.ht-supported-mcs': KeyInfo(can_disable=True), + 'rates.supported': KeyInfo(can_disable=True), + 'rates.vht-basic-mcs': KeyInfo(can_disable=True), + 'rates.vht-supported-mcs': KeyInfo(can_disable=True), + 'rx-chains': KeyInfo(can_disable=True), + 'security': KeyInfo(can_disable=True), + 'security.authentication-types': KeyInfo(can_disable=True), + 'security.disable-pmkid': KeyInfo(can_disable=True), + 'security.eap-methods': KeyInfo(can_disable=True), + 'security.eap-radius-accounting': KeyInfo(can_disable=True), + 'security.encryption': KeyInfo(can_disable=True), + 'security.group-encryption': KeyInfo(can_disable=True), + 'security.group-key-update': KeyInfo(), + 'security.passphrase': KeyInfo(can_disable=True), + 'security.tls-certificate': KeyInfo(), + 'security.tls-mode': KeyInfo(), + 'ssid': KeyInfo(can_disable=True), + 'tx-chains': KeyInfo(can_disable=True), + }, + ), ), ('caps-man', 'datapath'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'arp': KeyInfo(), - 'bridge': KeyInfo(can_disable=True), - 'bridge-cost': KeyInfo(can_disable=True), - 'bridge-horizon': KeyInfo(can_disable=True), - 'client-to-client-forwarding': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'interface-list': KeyInfo(can_disable=True), - 'l2mtu': KeyInfo(), - 'local-forwarding': KeyInfo(can_disable=True), - 'mtu': KeyInfo(), - 'name': KeyInfo(), - 'openflow-switch': KeyInfo(can_disable=True), - 'vlan-id': KeyInfo(can_disable=True), - 'vlan-mode': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'arp': KeyInfo(), + 'bridge': KeyInfo(can_disable=True), + 'bridge-cost': KeyInfo(can_disable=True), + 'bridge-horizon': KeyInfo(can_disable=True), + 'client-to-client-forwarding': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'interface-list': KeyInfo(can_disable=True), + 'l2mtu': KeyInfo(), + 'local-forwarding': KeyInfo(can_disable=True), + 'mtu': KeyInfo(), + 'name': KeyInfo(), + 'openflow-switch': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + 'vlan-mode': KeyInfo(can_disable=True), + }, + ), ), ('caps-man', 'manager', 'interface'): APIData( - fully_understood=True, - primary_keys=('interface', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'default': KeyInfo(), - 'disabled': KeyInfo(default=False), - 'forbid': KeyInfo(default=False), - 'interface': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'forbid': KeyInfo(default=False), + 'interface': KeyInfo(), + }, + ), ), ('caps-man', 'provisioning'): APIData( - fully_understood=True, - fields={ - 'action': KeyInfo(default='none'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'common-name-regexp': KeyInfo(default=''), - 'disabled': KeyInfo(default=False), - 'hw-supported-modes': KeyInfo(default=''), - 'identity-regexp': KeyInfo(default=''), - 'ip-address-ranges': KeyInfo(default=''), - 'master-configuration': KeyInfo(default='*FFFFFFFF'), - 'name-format': KeyInfo(default='cap'), - 'name-prefix': KeyInfo(default=''), - 'radio-mac': KeyInfo(default='00:00:00:00:00:00'), - 'slave-configurations': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='none'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'common-name-regexp': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'hw-supported-modes': KeyInfo(default=''), + 'identity-regexp': KeyInfo(default=''), + 'ip-address-ranges': KeyInfo(default=''), + 'master-configuration': KeyInfo(default='*FFFFFFFF'), + 'name-format': KeyInfo(default='cap'), + 'name-prefix': KeyInfo(default=''), + 'radio-mac': KeyInfo(default='00:00:00:00:00:00'), + 'slave-configurations': KeyInfo(default=''), + }, + ), ), ('caps-man', 'security'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'authentication-types': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disable-pmkid': KeyInfo(can_disable=True), - 'eap-methods': KeyInfo(can_disable=True), - 'eap-radius-accounting': KeyInfo(can_disable=True), - 'encryption': KeyInfo(can_disable=True), - 'group-encryption': KeyInfo(can_disable=True), - 'group-key-update': KeyInfo(), - 'name': KeyInfo(), - 'passphrase': KeyInfo(can_disable=True), - 'tls-certificate': KeyInfo(), - 'tls-mode': KeyInfo(), - } + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'authentication-types': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disable-pmkid': KeyInfo(can_disable=True), + 'eap-methods': KeyInfo(can_disable=True), + 'eap-radius-accounting': KeyInfo(can_disable=True), + 'encryption': KeyInfo(can_disable=True), + 'group-encryption': KeyInfo(can_disable=True), + 'group-key-update': KeyInfo(), + 'name': KeyInfo(), + 'passphrase': KeyInfo(can_disable=True), + 'tls-certificate': KeyInfo(), + 'tls-mode': KeyInfo(), + } + ), ), ('certificate', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'crl-download': KeyInfo(default=False), - 'crl-store': KeyInfo(default='ram'), - 'crl-use': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'crl-download': KeyInfo(default=False), + 'crl-store': KeyInfo(default='ram'), + 'crl-use': KeyInfo(default=False), + }, + ), ), ('interface', 'bridge', 'port'): APIData( - fully_understood=True, - primary_keys=('interface', ), - fields={ - 'auto-isolate': KeyInfo(default=False), - 'bpdu-guard': KeyInfo(default=False), - 'bridge': KeyInfo(required=True), - 'broadcast-flood': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'edge': KeyInfo(default='auto'), - 'fast-leave': KeyInfo(default=False), - 'frame-types': KeyInfo(default='admit-all'), - 'horizon': KeyInfo(default='none'), - 'hw': KeyInfo(default=True), - 'ingress-filtering': KeyInfo(default=True), - 'interface': KeyInfo(), - 'internal-path-cost': KeyInfo(default=10), - 'learn': KeyInfo(default='auto'), - 'multicast-router': KeyInfo(default='temporary-query'), - 'path-cost': KeyInfo(default=10), - 'point-to-point': KeyInfo(default='auto'), - 'priority': KeyInfo(default='0x80'), - 'pvid': KeyInfo(default=1), - 'restricted-role': KeyInfo(default=False), - 'restricted-tcn': KeyInfo(default=False), - 'tag-stacking': KeyInfo(default=False), - 'trusted': KeyInfo(default=False), - 'unknown-multicast-flood': KeyInfo(default=True), - 'unknown-unicast-flood': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'auto-isolate': KeyInfo(default=False), + 'bpdu-guard': KeyInfo(default=False), + 'bridge': KeyInfo(required=True), + 'broadcast-flood': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'edge': KeyInfo(default='auto'), + 'fast-leave': KeyInfo(default=False), + 'frame-types': KeyInfo(default='admit-all'), + 'horizon': KeyInfo(default='none'), + 'hw': KeyInfo(default=True), + 'ingress-filtering': KeyInfo(default=True), + 'interface': KeyInfo(), + 'internal-path-cost': KeyInfo(default=10), + 'learn': KeyInfo(default='auto'), + 'multicast-router': KeyInfo(default='temporary-query'), + 'path-cost': KeyInfo(default=10), + 'point-to-point': KeyInfo(default='auto'), + 'priority': KeyInfo(default='0x80'), + 'pvid': KeyInfo(default=1), + 'restricted-role': KeyInfo(default=False), + 'restricted-tcn': KeyInfo(default=False), + 'tag-stacking': KeyInfo(default=False), + 'trusted': KeyInfo(default=False), + 'unknown-multicast-flood': KeyInfo(default=True), + 'unknown-unicast-flood': KeyInfo(default=True), + }, + ), ), ('interface', 'bridge', 'mlag'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'bridge': KeyInfo(default='none'), - 'peer-port': KeyInfo(default='none'), - } + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'peer-port': KeyInfo(default='none'), + } + ), ), ('interface', 'bridge', 'port-controller'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'bridge': KeyInfo(default='none'), - 'cascade-ports': KeyInfo(default=''), - 'switch': KeyInfo(default='none'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'cascade-ports': KeyInfo(default=''), + 'switch': KeyInfo(default='none'), + }, + ), ), ('interface', 'bridge', 'port-extender'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'control-ports': KeyInfo(default=''), - 'excluded-ports': KeyInfo(default=''), - 'switch': KeyInfo(default='none'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'control-ports': KeyInfo(default=''), + 'excluded-ports': KeyInfo(default=''), + 'switch': KeyInfo(default='none'), + }, + ), ), ('interface', 'bridge', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-fast-path': KeyInfo(default=True), - 'use-ip-firewall': KeyInfo(default=False), - 'use-ip-firewall-for-pppoe': KeyInfo(default=False), - 'use-ip-firewall-for-vlan': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'use-ip-firewall': KeyInfo(default=False), + 'use-ip-firewall-for-pppoe': KeyInfo(default=False), + 'use-ip-firewall-for-vlan': KeyInfo(default=False), + }, + ), ), ('interface', 'bridge', 'vlan'): APIData( - fully_understood=True, - primary_keys=('bridge', 'vlan-ids', ), - fields={ - 'bridge': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'tagged': KeyInfo(default=''), - 'untagged': KeyInfo(default=''), - 'vlan-ids': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('bridge', 'vlan-ids', ), + fields={ + 'bridge': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'tagged': KeyInfo(default=''), + 'untagged': KeyInfo(default=''), + 'vlan-ids': KeyInfo(), + }, + ), ), ('ip', 'firewall', 'connection', 'tracking'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'enabled': KeyInfo(default='auto'), - 'generic-timeout': KeyInfo(default='10m'), - 'icmp-timeout': KeyInfo(default='10s'), - 'loose-tcp-tracking': KeyInfo(default=True), - 'tcp-close-timeout': KeyInfo(default='10s'), - 'tcp-close-wait-timeout': KeyInfo(default='10s'), - 'tcp-established-timeout': KeyInfo(default='1d'), - 'tcp-fin-wait-timeout': KeyInfo(default='10s'), - 'tcp-last-ack-timeout': KeyInfo(default='10s'), - 'tcp-max-retrans-timeout': KeyInfo(default='5m'), - 'tcp-syn-received-timeout': KeyInfo(default='5s'), - 'tcp-syn-sent-timeout': KeyInfo(default='5s'), - 'tcp-time-wait-timeout': KeyInfo(default='10s'), - 'tcp-unacked-timeout': KeyInfo(default='5m'), - 'udp-stream-timeout': KeyInfo(default='3m'), - 'udp-timeout': KeyInfo(default='10s'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default='auto'), + 'generic-timeout': KeyInfo(default='10m'), + 'icmp-timeout': KeyInfo(default='10s'), + 'loose-tcp-tracking': KeyInfo(default=True), + 'tcp-close-timeout': KeyInfo(default='10s'), + 'tcp-close-wait-timeout': KeyInfo(default='10s'), + 'tcp-established-timeout': KeyInfo(default='1d'), + 'tcp-fin-wait-timeout': KeyInfo(default='10s'), + 'tcp-last-ack-timeout': KeyInfo(default='10s'), + 'tcp-max-retrans-timeout': KeyInfo(default='5m'), + 'tcp-syn-received-timeout': KeyInfo(default='5s'), + 'tcp-syn-sent-timeout': KeyInfo(default='5s'), + 'tcp-time-wait-timeout': KeyInfo(default='10s'), + 'tcp-unacked-timeout': KeyInfo(default='5m'), + 'udp-stream-timeout': KeyInfo(default='3m'), + 'udp-timeout': KeyInfo(default='10s'), + }, + ), ), ('ip', 'neighbor', 'discovery-settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'discover-interface-list': KeyInfo(), - 'lldp-med-net-policy-vlan': KeyInfo(default='disabled'), - 'mode': KeyInfo(default='tx-and-rx'), - 'protocol': KeyInfo(default='cdp,lldp,mndp'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'discover-interface-list': KeyInfo(), + 'lldp-med-net-policy-vlan': KeyInfo(default='disabled'), + 'mode': KeyInfo(default='tx-and-rx'), + 'protocol': KeyInfo(default='cdp,lldp,mndp'), + }, + ), ), ('ip', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accept-redirects': KeyInfo(default=False), - 'accept-source-route': KeyInfo(default=False), - 'allow-fast-path': KeyInfo(default=True), - 'arp-timeout': KeyInfo(default='30s'), - 'icmp-rate-limit': KeyInfo(default=10), - 'icmp-rate-mask': KeyInfo(default='0x1818'), - 'ip-forward': KeyInfo(default=True), - 'max-neighbor-entries': KeyInfo(default=8192), - 'route-cache': KeyInfo(default=True), - 'rp-filter': KeyInfo(default=False), - 'secure-redirects': KeyInfo(default=True), - 'send-redirects': KeyInfo(default=True), - 'tcp-syncookies': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accept-redirects': KeyInfo(default=False), + 'accept-source-route': KeyInfo(default=False), + 'allow-fast-path': KeyInfo(default=True), + 'arp-timeout': KeyInfo(default='30s'), + 'icmp-rate-limit': KeyInfo(default=10), + 'icmp-rate-mask': KeyInfo(default='0x1818'), + 'ip-forward': KeyInfo(default=True), + 'max-neighbor-entries': KeyInfo(default=8192), + 'route-cache': KeyInfo(default=True), + 'rp-filter': KeyInfo(default=False), + 'secure-redirects': KeyInfo(default=True), + 'send-redirects': KeyInfo(default=True), + 'tcp-syncookies': KeyInfo(default=False), + }, + ), ), ('ipv6', 'address'): APIData( - fully_understood=True, - fields={ - 'address': KeyInfo(), - 'advertise': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'eui-64': KeyInfo(default=False), - 'from-pool': KeyInfo(), - 'interface': KeyInfo(required=True), - 'no-dad': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'advertise': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'eui-64': KeyInfo(default=False), + 'from-pool': KeyInfo(), + 'interface': KeyInfo(required=True), + 'no-dad': KeyInfo(default=False), + }, + ), ), ('ipv6', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), - 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), - 'disable-ipv6': KeyInfo(default=False), - 'forward': KeyInfo(default=True), - 'max-neighbor-entries': KeyInfo(default=8192), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), + 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), + 'disable-ipv6': KeyInfo(default=False), + 'forward': KeyInfo(default=True), + 'max-neighbor-entries': KeyInfo(default=8192), + }, + ), ), ('interface', 'detect-internet'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'detect-interface-list': KeyInfo(default='none'), - 'internet-interface-list': KeyInfo(default='none'), - 'lan-interface-list': KeyInfo(default='none'), - 'wan-interface-list': KeyInfo(default='none'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'detect-interface-list': KeyInfo(default='none'), + 'internet-interface-list': KeyInfo(default='none'), + 'lan-interface-list': KeyInfo(default='none'), + 'wan-interface-list': KeyInfo(default='none'), + }, + ), ), ('interface', 'l2tp-server', 'server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-fast-path': KeyInfo(default=False), - 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), - 'caller-id-type': KeyInfo(default='ip-address'), - 'default-profile': KeyInfo(default='default-encryption'), - 'enabled': KeyInfo(default=False), - 'ipsec-secret': KeyInfo(default=''), - 'keepalive-timeout': KeyInfo(default=30), - 'max-mru': KeyInfo(default=1450), - 'max-mtu': KeyInfo(default=1450), - 'max-sessions': KeyInfo(default='unlimited'), - 'mrru': KeyInfo(default='disabled'), - 'one-session-per-host': KeyInfo(default=False), - 'use-ipsec': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=False), + 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'caller-id-type': KeyInfo(default='ip-address'), + 'default-profile': KeyInfo(default='default-encryption'), + 'enabled': KeyInfo(default=False), + 'ipsec-secret': KeyInfo(default=''), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1450), + 'max-mtu': KeyInfo(default=1450), + 'max-sessions': KeyInfo(default='unlimited'), + 'mrru': KeyInfo(default='disabled'), + 'one-session-per-host': KeyInfo(default=False), + 'use-ipsec': KeyInfo(default=False), + }, + ), ), ('interface', 'ovpn-server', 'server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'auth': KeyInfo(), - 'cipher': KeyInfo(), - 'default-profile': KeyInfo(default='default'), - 'enabled': KeyInfo(default=False), - 'keepalive-timeout': KeyInfo(default=60), - 'mac-address': KeyInfo(), - 'max-mtu': KeyInfo(default=1500), - 'mode': KeyInfo(default='ip'), - 'netmask': KeyInfo(default=24), - 'port': KeyInfo(default=1194), - 'require-client-certificate': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auth': KeyInfo(), + 'cipher': KeyInfo(), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'mac-address': KeyInfo(), + 'max-mtu': KeyInfo(default=1500), + 'mode': KeyInfo(default='ip'), + 'netmask': KeyInfo(default=24), + 'port': KeyInfo(default=1194), + 'require-client-certificate': KeyInfo(default=False), + }, + ), ), ('interface', 'pptp-server', 'server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'authentication': KeyInfo(default='mschap1,mschap2'), - 'default-profile': KeyInfo(default='default-encryption'), - 'enabled': KeyInfo(default=False), - 'keepalive-timeout': KeyInfo(default=30), - 'max-mru': KeyInfo(default=1450), - 'max-mtu': KeyInfo(default=1450), - 'mrru': KeyInfo(default='disabled'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'authentication': KeyInfo(default='mschap1,mschap2'), + 'default-profile': KeyInfo(default='default-encryption'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=30), + 'max-mru': KeyInfo(default=1450), + 'max-mtu': KeyInfo(default=1450), + 'mrru': KeyInfo(default='disabled'), + }, + ), ), ('interface', 'sstp-server', 'server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), - 'certificate': KeyInfo(default='none'), - 'default-profile': KeyInfo(default='default'), - 'enabled': KeyInfo(default=False), - 'force-aes': KeyInfo(default=False), - 'keepalive-timeout': KeyInfo(default=60), - 'max-mru': KeyInfo(default=1500), - 'max-mtu': KeyInfo(default=1500), - 'mrru': KeyInfo(default='disabled'), - 'pfs': KeyInfo(default=False), - 'port': KeyInfo(default=443), - 'tls-version': KeyInfo(default='any'), - 'verify-client-certificate': KeyInfo(default='no'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'certificate': KeyInfo(default='none'), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'force-aes': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'max-mru': KeyInfo(default=1500), + 'max-mtu': KeyInfo(default=1500), + 'mrru': KeyInfo(default='disabled'), + 'pfs': KeyInfo(default=False), + 'port': KeyInfo(default=443), + 'tls-version': KeyInfo(default='any'), + 'verify-client-certificate': KeyInfo(default='no'), + }, + ), ), ('interface', 'wireguard'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'listen-port': KeyInfo(), - 'mtu': KeyInfo(default=1420), - 'name': KeyInfo(), - 'private-key': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'listen-port': KeyInfo(), + 'mtu': KeyInfo(default=1420), + 'name': KeyInfo(), + 'private-key': KeyInfo(), + }, + ), ), ('interface', 'wireguard', 'peers'): APIData( - fully_understood=True, - primary_keys=('public-key', 'interface'), - fields={ - 'allowed-address': KeyInfo(required=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'endpoint-address': KeyInfo(default=''), - 'endpoint-port': KeyInfo(default=0), - 'interface': KeyInfo(), - 'persistent-keepalive': KeyInfo(can_disable=True, remove_value=0), - 'preshared-key': KeyInfo(can_disable=True, remove_value=''), - 'public-key': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('public-key', 'interface'), + fields={ + 'allowed-address': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'endpoint-address': KeyInfo(default=''), + 'endpoint-port': KeyInfo(default=0), + 'interface': KeyInfo(), + 'persistent-keepalive': KeyInfo(can_disable=True, remove_value=0), + 'preshared-key': KeyInfo(can_disable=True, remove_value=''), + 'public-key': KeyInfo(), + }, + ), ), ('interface', 'wireless'): APIData( - fully_understood=True, - primary_keys=('name', ), - required_one_of=[['default-name', 'master-interface']], - fields={ - 'adaptive-noise-immunity': KeyInfo(default='none'), - 'allow-sharedkey': KeyInfo(default=False), - 'ampdu-priorities': KeyInfo(default=0), - 'amsdu-limit': KeyInfo(default=8192), - 'amsdu-threshold': KeyInfo(default=8192), - 'antenna-gain': KeyInfo(default=0), - 'antenna-mode': KeyInfo(), - 'area': KeyInfo(default=''), - 'arp': KeyInfo(default='enabled'), - 'arp-timeout': KeyInfo(default='auto'), - 'band': KeyInfo(), - 'basic-rates-a/g': KeyInfo(default='6Mbps'), - 'basic-rates-b': KeyInfo(default='1Mbps'), - 'bridge-mode': KeyInfo(default='enabled'), - 'channel-width': KeyInfo(default='20mhz'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'compression': KeyInfo(default=False), - 'country': KeyInfo(default='etsi'), - 'default-ap-tx-limit': KeyInfo(default=0), - 'default-authentication': KeyInfo(default=True), - 'default-client-tx-limit': KeyInfo(default=0), - 'default-forwarding': KeyInfo(default=True), - 'default-name': KeyInfo(), - 'disable-running-check': KeyInfo(default=False), - 'disabled': KeyInfo(default=True), - 'disconnect-timeout': KeyInfo(default='3s'), - 'distance': KeyInfo(default='dynamic'), - 'frame-lifetime': KeyInfo(default=0), - 'frequency': KeyInfo(), - 'frequency-mode': KeyInfo(default='regulatory-domain'), - 'frequency-offset': KeyInfo(default=0), - 'guard-interval': KeyInfo(default='any'), - 'hide-ssid': KeyInfo(default=False), - 'ht-basic-mcs': KeyInfo(), - 'ht-supported-mcs': KeyInfo(), - 'hw-fragmentation-threshold': KeyInfo(default='disabled'), - 'hw-protection-mode': KeyInfo(default='none'), - 'hw-protection-threshold': KeyInfo(default=0), - 'hw-retries': KeyInfo(default=7), - 'installation': KeyInfo(default='any'), - 'interworking-profile': KeyInfo(default='disabled'), - 'keepalive-frames': KeyInfo(default='enabled'), - 'l2mtu': KeyInfo(default=1600), - 'mac-address': KeyInfo(), - 'master-interface': KeyInfo(), - 'max-station-count': KeyInfo(default=2007), - 'mode': KeyInfo(default='ap-bridge'), - 'mtu': KeyInfo(default=1500), - 'multicast-buffering': KeyInfo(default='enabled'), - 'multicast-helper': KeyInfo(default='default'), - 'name': KeyInfo(), - 'noise-floor-threshold': KeyInfo(default='default'), - 'nv2-cell-radius': KeyInfo(default=30), - 'nv2-downlink-ratio': KeyInfo(default=50), - 'nv2-mode': KeyInfo(default='dynamic-downlink'), - 'nv2-noise-floor-offset': KeyInfo(default='default'), - 'nv2-preshared-key': KeyInfo(default=''), - 'nv2-qos': KeyInfo(default='default'), - 'nv2-queue-count': KeyInfo(default=2), - 'nv2-security': KeyInfo(default='disabled'), - 'nv2-sync-secret': KeyInfo(default=''), - 'on-fail-retry-time': KeyInfo(default='100ms'), - 'preamble-mode': KeyInfo(default='both'), - 'radio-name': KeyInfo(), - 'rate-selection': KeyInfo(default='advanced'), - 'rate-set': KeyInfo(default='default'), - 'running': KeyInfo(default=False), - 'rx-chains': KeyInfo(default='0,1'), - 'scan-list': KeyInfo(default='default'), - 'secondary-frequency': KeyInfo(default=''), - 'security-profile': KeyInfo(default='default'), - 'skip-dfs-channels': KeyInfo(default='disabled'), - 'ssid': KeyInfo(required=True), - 'station-bridge-clone-mac': KeyInfo(), - 'station-roaming': KeyInfo(default='disabled'), - 'supported-rates-a/g': KeyInfo(), - 'supported-rates-b': KeyInfo(), - 'tdma-period-size': KeyInfo(default=2), - 'tx-chains': KeyInfo(), - 'tx-power-mode': KeyInfo(default='default'), - 'update-stats-interval': KeyInfo(default='disabled'), - 'vlan-id': KeyInfo(default=1), - 'vlan-mode': KeyInfo(default='no-tag'), - 'wds-cost-range': KeyInfo(default='50-150'), - 'wds-default-bridge': KeyInfo(default='none'), - 'wds-default-cost': KeyInfo(default=100), - 'wds-ignore-ssid': KeyInfo(default=False), - 'wds-mode': KeyInfo(default='disabled'), - 'wireless-protocol': KeyInfo(default='any'), - 'wmm-support': KeyInfo(default='disabled'), - 'wps-mode': KeyInfo(default='push-button'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + required_one_of=[['default-name', 'master-interface']], + fields={ + 'adaptive-noise-immunity': KeyInfo(default='none'), + 'allow-sharedkey': KeyInfo(default=False), + 'ampdu-priorities': KeyInfo(default=0), + 'amsdu-limit': KeyInfo(default=8192), + 'amsdu-threshold': KeyInfo(default=8192), + 'antenna-gain': KeyInfo(default=0), + 'antenna-mode': KeyInfo(), + 'area': KeyInfo(default=''), + 'arp': KeyInfo(default='enabled'), + 'arp-timeout': KeyInfo(default='auto'), + 'band': KeyInfo(), + 'basic-rates-a/g': KeyInfo(default='6Mbps'), + 'basic-rates-b': KeyInfo(default='1Mbps'), + 'bridge-mode': KeyInfo(default='enabled'), + 'channel-width': KeyInfo(default='20mhz'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'compression': KeyInfo(default=False), + 'country': KeyInfo(default='etsi'), + 'default-ap-tx-limit': KeyInfo(default=0), + 'default-authentication': KeyInfo(default=True), + 'default-client-tx-limit': KeyInfo(default=0), + 'default-forwarding': KeyInfo(default=True), + 'default-name': KeyInfo(), + 'disable-running-check': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'disconnect-timeout': KeyInfo(default='3s'), + 'distance': KeyInfo(default='dynamic'), + 'frame-lifetime': KeyInfo(default=0), + 'frequency': KeyInfo(), + 'frequency-mode': KeyInfo(default='regulatory-domain'), + 'frequency-offset': KeyInfo(default=0), + 'guard-interval': KeyInfo(default='any'), + 'hide-ssid': KeyInfo(default=False), + 'ht-basic-mcs': KeyInfo(), + 'ht-supported-mcs': KeyInfo(), + 'hw-fragmentation-threshold': KeyInfo(default='disabled'), + 'hw-protection-mode': KeyInfo(default='none'), + 'hw-protection-threshold': KeyInfo(default=0), + 'hw-retries': KeyInfo(default=7), + 'installation': KeyInfo(default='any'), + 'interworking-profile': KeyInfo(default='disabled'), + 'keepalive-frames': KeyInfo(default='enabled'), + 'l2mtu': KeyInfo(default=1600), + 'mac-address': KeyInfo(), + 'master-interface': KeyInfo(), + 'max-station-count': KeyInfo(default=2007), + 'mode': KeyInfo(default='ap-bridge'), + 'mtu': KeyInfo(default=1500), + 'multicast-buffering': KeyInfo(default='enabled'), + 'multicast-helper': KeyInfo(default='default'), + 'name': KeyInfo(), + 'noise-floor-threshold': KeyInfo(default='default'), + 'nv2-cell-radius': KeyInfo(default=30), + 'nv2-downlink-ratio': KeyInfo(default=50), + 'nv2-mode': KeyInfo(default='dynamic-downlink'), + 'nv2-noise-floor-offset': KeyInfo(default='default'), + 'nv2-preshared-key': KeyInfo(default=''), + 'nv2-qos': KeyInfo(default='default'), + 'nv2-queue-count': KeyInfo(default=2), + 'nv2-security': KeyInfo(default='disabled'), + 'nv2-sync-secret': KeyInfo(default=''), + 'on-fail-retry-time': KeyInfo(default='100ms'), + 'preamble-mode': KeyInfo(default='both'), + 'radio-name': KeyInfo(), + 'rate-selection': KeyInfo(default='advanced'), + 'rate-set': KeyInfo(default='default'), + 'running': KeyInfo(default=False), + 'rx-chains': KeyInfo(default='0,1'), + 'scan-list': KeyInfo(default='default'), + 'secondary-frequency': KeyInfo(default=''), + 'security-profile': KeyInfo(default='default'), + 'skip-dfs-channels': KeyInfo(default='disabled'), + 'ssid': KeyInfo(required=True), + 'station-bridge-clone-mac': KeyInfo(), + 'station-roaming': KeyInfo(default='disabled'), + 'supported-rates-a/g': KeyInfo(), + 'supported-rates-b': KeyInfo(), + 'tdma-period-size': KeyInfo(default=2), + 'tx-chains': KeyInfo(), + 'tx-power-mode': KeyInfo(default='default'), + 'update-stats-interval': KeyInfo(default='disabled'), + 'vlan-id': KeyInfo(default=1), + 'vlan-mode': KeyInfo(default='no-tag'), + 'wds-cost-range': KeyInfo(default='50-150'), + 'wds-default-bridge': KeyInfo(default='none'), + 'wds-default-cost': KeyInfo(default=100), + 'wds-ignore-ssid': KeyInfo(default=False), + 'wds-mode': KeyInfo(default='disabled'), + 'wireless-protocol': KeyInfo(default='any'), + 'wmm-support': KeyInfo(default='disabled'), + 'wps-mode': KeyInfo(default='push-button'), + }, + ), ), ('interface', 'wireless', 'align'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'active-mode': KeyInfo(default=True), - 'audio-max': KeyInfo(default=-20), - 'audio-min': KeyInfo(default=-100), - 'audio-monitor': KeyInfo(default='00:00:00:00:00:00'), - 'filter-mac': KeyInfo(default='00:00:00:00:00:00'), - 'frame-size': KeyInfo(default=300), - 'frames-per-second': KeyInfo(default=25), - 'receive-all': KeyInfo(default=False), - 'ssid-all': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'active-mode': KeyInfo(default=True), + 'audio-max': KeyInfo(default=-20), + 'audio-min': KeyInfo(default=-100), + 'audio-monitor': KeyInfo(default='00:00:00:00:00:00'), + 'filter-mac': KeyInfo(default='00:00:00:00:00:00'), + 'frame-size': KeyInfo(default=300), + 'frames-per-second': KeyInfo(default=25), + 'receive-all': KeyInfo(default=False), + 'ssid-all': KeyInfo(default=False), + }, + ), ), ('interface', 'wireless', 'cap'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'bridge': KeyInfo(default='none'), - 'caps-man-addresses': KeyInfo(default=''), - 'caps-man-certificate-common-names': KeyInfo(default=''), - 'caps-man-names': KeyInfo(default=''), - 'certificate': KeyInfo(default='none'), - 'discovery-interfaces': KeyInfo(default=''), - 'enabled': KeyInfo(default=False), - 'interfaces': KeyInfo(default=''), - 'lock-to-caps-man': KeyInfo(default=False), - 'static-virtual': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'bridge': KeyInfo(default='none'), + 'caps-man-addresses': KeyInfo(default=''), + 'caps-man-certificate-common-names': KeyInfo(default=''), + 'caps-man-names': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'discovery-interfaces': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'interfaces': KeyInfo(default=''), + 'lock-to-caps-man': KeyInfo(default=False), + 'static-virtual': KeyInfo(default=False), + }, + ), ), ('interface', 'wireless', 'security-profiles'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'authentication-types': KeyInfo(), - 'disable-pmkid': KeyInfo(default=False), - 'disabled': KeyInfo(default=True), - 'eap-methods': KeyInfo(), - 'group-ciphers': KeyInfo(), - 'group-key-update': KeyInfo(default='5m'), - 'interim-update': KeyInfo(), - 'management-protection': KeyInfo(default='disabled'), - 'management-protection-key': KeyInfo(default=''), - 'mode': KeyInfo(default='none'), - 'mschapv2-password': KeyInfo(default=''), - 'mschapv2-username': KeyInfo(default=''), - 'name': KeyInfo(), - 'radius-called-format': KeyInfo(), - 'radius-eap-accounting': KeyInfo(default=False), - 'radius-mac-accounting': KeyInfo(default=False), - 'radius-mac-authentication': KeyInfo(default=False), - 'radius-mac-caching': KeyInfo(default='disabled'), - 'radius-mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), - 'radius-mac-mode': KeyInfo(default='as-username'), - 'static-algo-0': KeyInfo(default='none'), - 'static-algo-1': KeyInfo(default='none'), - 'static-algo-2': KeyInfo(default='none'), - 'static-algo-3': KeyInfo(default='none'), - 'static-key-0': KeyInfo(), - 'static-key-1': KeyInfo(), - 'static-key-2': KeyInfo(), - 'static-key-3': KeyInfo(), - 'static-sta-private-algo': KeyInfo(default='none'), - 'static-sta-private-key': KeyInfo(), - 'static-transmit-key': KeyInfo(), - 'supplicant-identity': KeyInfo(default='MikroTik'), - 'tls-certificate': KeyInfo(default='none'), - 'tls-mode': KeyInfo(), - 'unicast-ciphers': KeyInfo(), - 'wpa-pre-shared-key': KeyInfo(), - 'wpa2-pre-shared-key': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'authentication-types': KeyInfo(), + 'disable-pmkid': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'eap-methods': KeyInfo(), + 'group-ciphers': KeyInfo(), + 'group-key-update': KeyInfo(default='5m'), + 'interim-update': KeyInfo(), + 'management-protection': KeyInfo(default='disabled'), + 'management-protection-key': KeyInfo(default=''), + 'mode': KeyInfo(default='none'), + 'mschapv2-password': KeyInfo(default=''), + 'mschapv2-username': KeyInfo(default=''), + 'name': KeyInfo(), + 'radius-called-format': KeyInfo(), + 'radius-eap-accounting': KeyInfo(default=False), + 'radius-mac-accounting': KeyInfo(default=False), + 'radius-mac-authentication': KeyInfo(default=False), + 'radius-mac-caching': KeyInfo(default='disabled'), + 'radius-mac-format': KeyInfo(default='XX:XX:XX:XX:XX:XX'), + 'radius-mac-mode': KeyInfo(default='as-username'), + 'static-algo-0': KeyInfo(default='none'), + 'static-algo-1': KeyInfo(default='none'), + 'static-algo-2': KeyInfo(default='none'), + 'static-algo-3': KeyInfo(default='none'), + 'static-key-0': KeyInfo(), + 'static-key-1': KeyInfo(), + 'static-key-2': KeyInfo(), + 'static-key-3': KeyInfo(), + 'static-sta-private-algo': KeyInfo(default='none'), + 'static-sta-private-key': KeyInfo(), + 'static-transmit-key': KeyInfo(), + 'supplicant-identity': KeyInfo(default='MikroTik'), + 'tls-certificate': KeyInfo(default='none'), + 'tls-mode': KeyInfo(), + 'unicast-ciphers': KeyInfo(), + 'wpa-pre-shared-key': KeyInfo(), + 'wpa2-pre-shared-key': KeyInfo(), + }, + ), ), ('interface', 'wireless', 'sniffer'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'channel-time': KeyInfo(default='200ms'), - 'file-limit': KeyInfo(default=10), - 'file-name': KeyInfo(default=''), - 'memory-limit': KeyInfo(default=10), - 'multiple-channels': KeyInfo(default=False), - 'only-headers': KeyInfo(default=False), - 'receive-errors': KeyInfo(default=False), - 'streaming-enabled': KeyInfo(default=False), - 'streaming-max-rate': KeyInfo(default=0), - 'streaming-server': KeyInfo(default='0.0.0.0'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'channel-time': KeyInfo(default='200ms'), + 'file-limit': KeyInfo(default=10), + 'file-name': KeyInfo(default=''), + 'memory-limit': KeyInfo(default=10), + 'multiple-channels': KeyInfo(default=False), + 'only-headers': KeyInfo(default=False), + 'receive-errors': KeyInfo(default=False), + 'streaming-enabled': KeyInfo(default=False), + 'streaming-max-rate': KeyInfo(default=0), + 'streaming-server': KeyInfo(default='0.0.0.0'), + }, + ), ), ('interface', 'wireless', 'snooper'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'channel-time': KeyInfo(default='200ms'), - 'multiple-channels': KeyInfo(default=True), - 'receive-errors': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'channel-time': KeyInfo(default='200ms'), + 'multiple-channels': KeyInfo(default=True), + 'receive-errors': KeyInfo(default=False), + }, + ), ), ('iot', 'modbus'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'disabled': KeyInfo(default=True), - 'hardware-port': KeyInfo(default='modbus'), - 'tcp-port': KeyInfo(default=502), - 'timeout': KeyInfo(default=1000), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=True), + 'hardware-port': KeyInfo(default='modbus'), + 'tcp-port': KeyInfo(default=502), + 'timeout': KeyInfo(default=1000), + }, + ), ), ('ip', 'accounting'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'account-local-traffic': KeyInfo(default=False), - 'enabled': KeyInfo(default=False), - 'threshold': KeyInfo(default=256), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'account-local-traffic': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'threshold': KeyInfo(default=256), + }, + ), ), ('ip', 'accounting', 'web-access'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accessible-via-web': KeyInfo(default=False), - 'address': KeyInfo(default='0.0.0.0/0'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accessible-via-web': KeyInfo(default=False), + 'address': KeyInfo(default='0.0.0.0/0'), + }, + ), ), ('ip', 'address'): APIData( - fully_understood=True, - primary_keys=('address', 'interface', ), - fields={ - 'address': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interface': KeyInfo(), - 'network': KeyInfo(automatically_computed_from=('address', )), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('address', 'interface', ), + fields={ + 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'network': KeyInfo(automatically_computed_from=('address', )), + }, + ), ), ('ip', 'arp'): APIData( - fully_understood=True, - fields={ - 'address': KeyInfo(default='0.0.0.0'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interface': KeyInfo(required=True), - 'mac-address': KeyInfo(default='00:00:00:00:00:00'), - 'published': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'address': KeyInfo(default='0.0.0.0'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'mac-address': KeyInfo(default='00:00:00:00:00:00'), + 'published': KeyInfo(default=False), + }, + ), ), ('ip', 'cloud'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'ddns-enabled': KeyInfo(default=False), - 'ddns-update-interval': KeyInfo(default='none'), - 'update-time': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'ddns-enabled': KeyInfo(default=False), + 'ddns-update-interval': KeyInfo(default='none'), + 'update-time': KeyInfo(default=True), + }, + ), ), ('ip', 'cloud', 'advanced'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'use-local-address': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'use-local-address': KeyInfo(default=False), + }, + ), ), ('ip', 'dhcp-client'): APIData( - fully_understood=True, - primary_keys=('interface', ), - fields={ - 'add-default-route': KeyInfo(default=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'default-route-distance': KeyInfo(default=1), - 'dhcp-options': KeyInfo(default='hostname,clientid', can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interface': KeyInfo(), - 'script': KeyInfo(can_disable=True), - 'use-peer-dns': KeyInfo(default=True), - 'use-peer-ntp': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'add-default-route': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dhcp-options': KeyInfo(default='hostname,clientid', can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'script': KeyInfo(can_disable=True), + 'use-peer-dns': KeyInfo(default=True), + 'use-peer-ntp': KeyInfo(default=True), + }, + ), ), ('ip', 'dhcp-server', 'config'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accounting': KeyInfo(default=True), - 'interim-update': KeyInfo(default='0s'), - 'store-leases-disk': KeyInfo(default='5m'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'store-leases-disk': KeyInfo(default='5m'), + }, + ), ), ('ip', 'dhcp-server', 'lease'): APIData( - fully_understood=True, - primary_keys=('server', 'address', ), - fields={ - 'address': KeyInfo(), - 'address-lists': KeyInfo(default=''), - 'always-broadcast': KeyInfo(), - 'client-id': KeyInfo(can_disable=True, remove_value=''), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'dhcp-option': KeyInfo(default=''), - 'disabled': KeyInfo(default=False), - 'insert-queue-before': KeyInfo(can_disable=True), - 'mac-address': KeyInfo(can_disable=True, remove_value=''), - 'server': KeyInfo(absent_value='all'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('server', 'address', ), + fields={ + 'address': KeyInfo(), + 'address-lists': KeyInfo(default=''), + 'always-broadcast': KeyInfo(), + 'client-id': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True, remove_value=''), + 'server': KeyInfo(absent_value='all'), + }, + ), ), ('ip', 'dhcp-server', 'network'): APIData( - fully_understood=True, - primary_keys=('address', ), - fields={ - 'address': KeyInfo(), - 'boot-file-name': KeyInfo(default=''), - 'caps-manager': KeyInfo(default=''), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'dhcp-option': KeyInfo(default=''), - 'dhcp-option-set': KeyInfo(default=''), - 'dns-none': KeyInfo(default=False), - 'dns-server': KeyInfo(default=''), - 'domain': KeyInfo(default=''), - 'gateway': KeyInfo(default=''), - 'netmask': KeyInfo(can_disable=True, remove_value=0), - 'next-server': KeyInfo(can_disable=True), - 'ntp-server': KeyInfo(default=''), - 'wins-server': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('address', ), + fields={ + 'address': KeyInfo(), + 'boot-file-name': KeyInfo(default=''), + 'caps-manager': KeyInfo(default=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'dhcp-option-set': KeyInfo(default=''), + 'dns-none': KeyInfo(default=False), + 'dns-server': KeyInfo(default=''), + 'domain': KeyInfo(default=''), + 'gateway': KeyInfo(default=''), + 'netmask': KeyInfo(can_disable=True, remove_value=0), + 'next-server': KeyInfo(can_disable=True), + 'ntp-server': KeyInfo(default=''), + 'wins-server': KeyInfo(default=''), + }, + ), ), ('ip', 'dns'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-remote-requests': KeyInfo(), - 'cache-max-ttl': KeyInfo(default='1w'), - 'cache-size': KeyInfo(default='2048KiB'), - 'max-concurrent-queries': KeyInfo(default=100), - 'max-concurrent-tcp-sessions': KeyInfo(default=20), - 'max-udp-packet-size': KeyInfo(default=4096), - 'query-server-timeout': KeyInfo(default='2s'), - 'query-total-timeout': KeyInfo(default='10s'), - 'servers': KeyInfo(default=''), - 'use-doh-server': KeyInfo(default=''), - 'verify-doh-cert': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-remote-requests': KeyInfo(), + 'cache-max-ttl': KeyInfo(default='1w'), + 'cache-size': KeyInfo(default='2048KiB'), + 'max-concurrent-queries': KeyInfo(default=100), + 'max-concurrent-tcp-sessions': KeyInfo(default=20), + 'max-udp-packet-size': KeyInfo(default=4096), + 'query-server-timeout': KeyInfo(default='2s'), + 'query-total-timeout': KeyInfo(default='10s'), + 'servers': KeyInfo(default=''), + 'use-doh-server': KeyInfo(default=''), + 'verify-doh-cert': KeyInfo(default=False), + }, + ), ), ('ip', 'dns', 'static'): APIData( - fully_understood=True, - required_one_of=[['name', 'regexp']], - mutually_exclusive=[['name', 'regexp']], - fields={ - 'address': KeyInfo(), - 'address-list': KeyInfo(), - 'cname': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'forward-to': KeyInfo(), - 'match-subdomain': KeyInfo(default=False), - 'mx-exchange': KeyInfo(), - 'mx-preference': KeyInfo(), - 'name': KeyInfo(), - 'ns': KeyInfo(), - 'regexp': KeyInfo(), - 'srv-port': KeyInfo(), - 'srv-priority': KeyInfo(), - 'srv-target': KeyInfo(), - 'srv-weight': KeyInfo(), - 'text': KeyInfo(), - 'ttl': KeyInfo(default='1d'), - 'type': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + required_one_of=[['name', 'regexp']], + mutually_exclusive=[['name', 'regexp']], + fields={ + 'address': KeyInfo(), + 'address-list': KeyInfo(), + 'cname': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'forward-to': KeyInfo(), + 'match-subdomain': KeyInfo(default=False), + 'mx-exchange': KeyInfo(), + 'mx-preference': KeyInfo(), + 'name': KeyInfo(), + 'ns': KeyInfo(), + 'regexp': KeyInfo(), + 'srv-port': KeyInfo(), + 'srv-priority': KeyInfo(), + 'srv-target': KeyInfo(), + 'srv-weight': KeyInfo(), + 'text': KeyInfo(), + 'ttl': KeyInfo(default='1d'), + 'type': KeyInfo(), + }, + ), ), ('ip', 'firewall', 'address-list'): APIData( - fully_understood=True, - primary_keys=('address', 'list', ), - fields={ - 'address': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'list': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('address', 'list', ), + fields={ + 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'list': KeyInfo(), + }, + ), ), ('ip', 'firewall', 'filter'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-nat-state': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-state': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'fragment': KeyInfo(can_disable=True), - 'hotspot': KeyInfo(can_disable=True), - 'hw-offload': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'layer7-protocol': KeyInfo(can_disable=True), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'p2p': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'psd': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'reject-with': KeyInfo(), - 'routing-mark': KeyInfo(can_disable=True), - 'routing-table': KeyInfo(can_disable=True), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - 'ttl': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-nat-state': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'hw-offload': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'p2p': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'reject-with': KeyInfo(), + 'routing-mark': KeyInfo(can_disable=True), + 'routing-table': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ), ('ip', 'firewall', 'mangle'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-nat-state': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-state': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'fragment': KeyInfo(can_disable=True), - 'hotspot': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'layer7-protocol': KeyInfo(can_disable=True), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'new-connection-mark': KeyInfo(can_disable=True), - 'new-dscp': KeyInfo(can_disable=True), - 'new-mss': KeyInfo(can_disable=True), - 'new-packet-mark': KeyInfo(can_disable=True), - 'new-priority': KeyInfo(can_disable=True), - 'new-routing-mark': KeyInfo(can_disable=True), - 'new-ttl': KeyInfo(can_disable=True), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'p2p': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'passthrough': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'psd': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'route-dst': KeyInfo(can_disable=True), - 'routing-mark': KeyInfo(can_disable=True), - 'routing-table': KeyInfo(can_disable=True), - 'sniff-id': KeyInfo(can_disable=True), - 'sniff-target': KeyInfo(can_disable=True), - 'sniff-target-port': KeyInfo(can_disable=True), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - 'ttl': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-nat-state': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'new-connection-mark': KeyInfo(can_disable=True), + 'new-dscp': KeyInfo(can_disable=True), + 'new-mss': KeyInfo(can_disable=True), + 'new-packet-mark': KeyInfo(can_disable=True), + 'new-priority': KeyInfo(can_disable=True), + 'new-routing-mark': KeyInfo(can_disable=True), + 'new-ttl': KeyInfo(can_disable=True), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'p2p': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'passthrough': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'route-dst': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'routing-table': KeyInfo(can_disable=True), + 'sniff-id': KeyInfo(can_disable=True), + 'sniff-target': KeyInfo(can_disable=True), + 'sniff-target-port': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ), ('ip', 'firewall', 'nat'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'fragment': KeyInfo(can_disable=True), - 'hotspot': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'layer7-protocol': KeyInfo(can_disable=True), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'psd': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'realm': KeyInfo(can_disable=True), - 'routing-mark': KeyInfo(can_disable=True), - 'same-not-by-dst': KeyInfo(), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - 'to-addresses': KeyInfo(can_disable=True), - 'to-ports': KeyInfo(can_disable=True), - 'ttl': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'realm': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'same-not-by-dst': KeyInfo(), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'to-addresses': KeyInfo(can_disable=True), + 'to-ports': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ), ('ip', 'firewall', 'raw'): APIData( - fully_understood=True, - stratify_keys=('chain',), - fields={ - 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'fragment': KeyInfo(can_disable=True), - 'hotspot': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'psd': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - 'ttl': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain',), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'fragment': KeyInfo(can_disable=True), + 'hotspot': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'ipv4-options': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'psd': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'ttl': KeyInfo(can_disable=True), + }, + ), ), ('ip', 'hotspot', 'user'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(), - 'name': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(), + 'name': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accounting': KeyInfo(default=True), - 'interim-update': KeyInfo(default='0s'), - 'xauth-use-radius': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'xauth-use-radius': KeyInfo(default=False), + }, + ), ), ('ip', 'proxy'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'always-from-cache': KeyInfo(default=False), - 'anonymous': KeyInfo(default=False), - 'cache-administrator': KeyInfo(default='webmaster'), - 'cache-hit-dscp': KeyInfo(default=4), - 'cache-on-disk': KeyInfo(default=False), - 'cache-path': KeyInfo(default='web-proxy'), - 'enabled': KeyInfo(default=False), - 'max-cache-object-size': KeyInfo(default='2048KiB'), - 'max-cache-size': KeyInfo(default='unlimited'), - 'max-client-connections': KeyInfo(default=600), - 'max-fresh-time': KeyInfo(default='3d'), - 'max-server-connections': KeyInfo(default=600), - 'parent-proxy': KeyInfo(default='::'), - 'parent-proxy-port': KeyInfo(default=0), - 'port': KeyInfo(default=8080), - 'serialize-connections': KeyInfo(default=False), - 'src-address': KeyInfo(default='::'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'always-from-cache': KeyInfo(default=False), + 'anonymous': KeyInfo(default=False), + 'cache-administrator': KeyInfo(default='webmaster'), + 'cache-hit-dscp': KeyInfo(default=4), + 'cache-on-disk': KeyInfo(default=False), + 'cache-path': KeyInfo(default='web-proxy'), + 'enabled': KeyInfo(default=False), + 'max-cache-object-size': KeyInfo(default='2048KiB'), + 'max-cache-size': KeyInfo(default='unlimited'), + 'max-client-connections': KeyInfo(default=600), + 'max-fresh-time': KeyInfo(default='3d'), + 'max-server-connections': KeyInfo(default=600), + 'parent-proxy': KeyInfo(default='::'), + 'parent-proxy-port': KeyInfo(default=0), + 'port': KeyInfo(default=8080), + 'serialize-connections': KeyInfo(default=False), + 'src-address': KeyInfo(default='::'), + }, + ), ), ('ip', 'smb'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-guests': KeyInfo(default=True), - 'comment': KeyInfo(default='MikrotikSMB'), - 'domain': KeyInfo(default='MSHOME'), - 'enabled': KeyInfo(default=False), - 'interfaces': KeyInfo(default='all'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-guests': KeyInfo(default=True), + 'comment': KeyInfo(default='MikrotikSMB'), + 'domain': KeyInfo(default='MSHOME'), + 'enabled': KeyInfo(default=False), + 'interfaces': KeyInfo(default='all'), + }, + ), ), ('ip', 'smb', 'shares'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'directory': KeyInfo(), - 'disabled': KeyInfo(), - 'max-sessions': KeyInfo(), - 'name': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'directory': KeyInfo(), + 'disabled': KeyInfo(), + 'max-sessions': KeyInfo(), + 'name': KeyInfo(), + }, + ), ), ('ip', 'smb', 'users'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'name': KeyInfo(), - 'password': KeyInfo(), - 'read-only': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'name': KeyInfo(), + 'password': KeyInfo(), + 'read-only': KeyInfo(), + }, + ), ), ('ip', 'socks'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'auth-method': KeyInfo(default='none'), - 'connection-idle-timeout': KeyInfo(default='2m'), - 'enabled': KeyInfo(default=False), - 'max-connections': KeyInfo(default=200), - 'port': KeyInfo(default=1080), - 'version': KeyInfo(default=4), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auth-method': KeyInfo(default='none'), + 'connection-idle-timeout': KeyInfo(default='2m'), + 'enabled': KeyInfo(default=False), + 'max-connections': KeyInfo(default=200), + 'port': KeyInfo(default=1080), + 'version': KeyInfo(default=4), + }, + ), ), ('ip', 'ssh'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-none-crypto': KeyInfo(default=False), - 'always-allow-password-login': KeyInfo(default=False), - 'forwarding-enabled': KeyInfo(default=False), - 'host-key-size': KeyInfo(default=2048), - 'strong-crypto': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-none-crypto': KeyInfo(default=False), + 'always-allow-password-login': KeyInfo(default=False), + 'forwarding-enabled': KeyInfo(default=False), + 'host-key-size': KeyInfo(default=2048), + 'strong-crypto': KeyInfo(default=False), + }, + ), ), ('ip', 'tftp', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'max-block-size': KeyInfo(default=4096), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'max-block-size': KeyInfo(default=4096), + }, + ), ), ('ip', 'traffic-flow'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'active-flow-timeout': KeyInfo(default='30m'), - 'cache-entries': KeyInfo(default='32k'), - 'enabled': KeyInfo(default=False), - 'inactive-flow-timeout': KeyInfo(default='15s'), - 'interfaces': KeyInfo(default='all'), - 'packet-sampling': KeyInfo(default=False), - 'sampling-interval': KeyInfo(default=0), - 'sampling-space': KeyInfo(default=0), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'active-flow-timeout': KeyInfo(default='30m'), + 'cache-entries': KeyInfo(default='32k'), + 'enabled': KeyInfo(default=False), + 'inactive-flow-timeout': KeyInfo(default='15s'), + 'interfaces': KeyInfo(default='all'), + 'packet-sampling': KeyInfo(default=False), + 'sampling-interval': KeyInfo(default=0), + 'sampling-space': KeyInfo(default=0), + }, + ), ), ('ip', 'traffic-flow', 'ipfix'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'bytes': KeyInfo(default=True), - 'dst-address': KeyInfo(default=True), - 'dst-address-mask': KeyInfo(default=True), - 'dst-mac-address': KeyInfo(default=True), - 'dst-port': KeyInfo(default=True), - 'first-forwarded': KeyInfo(default=True), - 'gateway': KeyInfo(default=True), - 'icmp-code': KeyInfo(default=True), - 'icmp-type': KeyInfo(default=True), - 'igmp-type': KeyInfo(default=True), - 'in-interface': KeyInfo(default=True), - 'ip-header-length': KeyInfo(default=True), - 'ip-total-length': KeyInfo(default=True), - 'ipv6-flow-label': KeyInfo(default=True), - 'is-multicast': KeyInfo(default=True), - 'last-forwarded': KeyInfo(default=True), - 'nat-dst-address': KeyInfo(default=True), - 'nat-dst-port': KeyInfo(default=True), - 'nat-events': KeyInfo(default=False), - 'nat-src-address': KeyInfo(default=True), - 'nat-src-port': KeyInfo(default=True), - 'out-interface': KeyInfo(default=True), - 'packets': KeyInfo(default=True), - 'protocol': KeyInfo(default=True), - 'src-address': KeyInfo(default=True), - 'src-address-mask': KeyInfo(default=True), - 'src-mac-address': KeyInfo(default=True), - 'src-port': KeyInfo(default=True), - 'sys-init-time': KeyInfo(default=True), - 'tcp-ack-num': KeyInfo(default=True), - 'tcp-flags': KeyInfo(default=True), - 'tcp-seq-num': KeyInfo(default=True), - 'tcp-window-size': KeyInfo(default=True), - 'tos': KeyInfo(default=True), - 'ttl': KeyInfo(default=True), - 'udp-length': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'bytes': KeyInfo(default=True), + 'dst-address': KeyInfo(default=True), + 'dst-address-mask': KeyInfo(default=True), + 'dst-mac-address': KeyInfo(default=True), + 'dst-port': KeyInfo(default=True), + 'first-forwarded': KeyInfo(default=True), + 'gateway': KeyInfo(default=True), + 'icmp-code': KeyInfo(default=True), + 'icmp-type': KeyInfo(default=True), + 'igmp-type': KeyInfo(default=True), + 'in-interface': KeyInfo(default=True), + 'ip-header-length': KeyInfo(default=True), + 'ip-total-length': KeyInfo(default=True), + 'ipv6-flow-label': KeyInfo(default=True), + 'is-multicast': KeyInfo(default=True), + 'last-forwarded': KeyInfo(default=True), + 'nat-dst-address': KeyInfo(default=True), + 'nat-dst-port': KeyInfo(default=True), + 'nat-events': KeyInfo(default=False), + 'nat-src-address': KeyInfo(default=True), + 'nat-src-port': KeyInfo(default=True), + 'out-interface': KeyInfo(default=True), + 'packets': KeyInfo(default=True), + 'protocol': KeyInfo(default=True), + 'src-address': KeyInfo(default=True), + 'src-address-mask': KeyInfo(default=True), + 'src-mac-address': KeyInfo(default=True), + 'src-port': KeyInfo(default=True), + 'sys-init-time': KeyInfo(default=True), + 'tcp-ack-num': KeyInfo(default=True), + 'tcp-flags': KeyInfo(default=True), + 'tcp-seq-num': KeyInfo(default=True), + 'tcp-window-size': KeyInfo(default=True), + 'tos': KeyInfo(default=True), + 'ttl': KeyInfo(default=True), + 'udp-length': KeyInfo(default=True), + }, + ), ), ('ip', 'traffic-flow', 'target'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'address': KeyInfo(), - 'disabled': KeyInfo(default=False), - 'dst-address': KeyInfo(), - 'port': KeyInfo(default=2055), - 'src-address': KeyInfo(), - 'v9-template-refresh': KeyInfo(default=20), - 'v9-template-timeout': KeyInfo(), - 'version': KeyInfo(), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'dst-address': KeyInfo(), + 'port': KeyInfo(default=2055), + 'src-address': KeyInfo(), + 'v9-template-refresh': KeyInfo(default=20), + 'v9-template-timeout': KeyInfo(), + 'version': KeyInfo(), + }, + ), ), ('ip', 'upnp'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-disable-external-interface': KeyInfo(default=False), - 'enabled': KeyInfo(default=False), - 'show-dummy-rule': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-disable-external-interface': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'show-dummy-rule': KeyInfo(default=True), + }, + ), ), ('ipv6', 'dhcp-client'): APIData( - fully_understood=True, - primary_keys=('interface', 'request'), - fields={ - 'add-default-route': KeyInfo(default=False), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'default-route-distance': KeyInfo(default=1), - 'dhcp-options': KeyInfo(default=''), - 'disabled': KeyInfo(default=False), - 'interface': KeyInfo(), - 'pool-name': KeyInfo(required=True), - 'pool-prefix-length': KeyInfo(default=64), - 'prefix-hint': KeyInfo(default='::/0'), - 'request': KeyInfo(), - 'use-peer-dns': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', 'request'), + fields={ + 'add-default-route': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-route-distance': KeyInfo(default=1), + 'dhcp-options': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'pool-name': KeyInfo(required=True), + 'pool-prefix-length': KeyInfo(default=64), + 'prefix-hint': KeyInfo(default='::/0'), + 'request': KeyInfo(), + 'use-peer-dns': KeyInfo(default=True), + }, + ), ), ('ipv6', 'dhcp-server'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'address-pool': KeyInfo(required=True), - 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), - 'binding-script': KeyInfo(can_disable=True, remove_value=''), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'dhcp-option': KeyInfo(default=''), - 'disabled': KeyInfo(default=False), - 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), - 'interface': KeyInfo(required=True), - 'lease-time': KeyInfo(default='3d'), - 'name': KeyInfo(), - 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), - 'preference': KeyInfo(default=255), - 'rapid-commit': KeyInfo(default=True), - 'route-distance': KeyInfo(default=1), - 'use-radius': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(required=True), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'binding-script': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), + 'interface': KeyInfo(required=True), + 'lease-time': KeyInfo(default='3d'), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'preference': KeyInfo(default=255), + 'rapid-commit': KeyInfo(default=True), + 'route-distance': KeyInfo(default=1), + 'use-radius': KeyInfo(default=False), + }, + ), ), ('ipv6', 'dhcp-server', 'option'): APIData( - fully_understood=True, - primary_keys=('name',), - fields={ - 'code': KeyInfo(required=True), - 'name': KeyInfo(), - 'value': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'code': KeyInfo(required=True), + 'name': KeyInfo(), + 'value': KeyInfo(default=''), + }, + ), ), ('ipv6', 'firewall', 'address-list'): APIData( - fully_understood=True, - primary_keys=('address', 'list', ), - fields={ - 'address': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'list': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('address', 'list', ), + fields={ + 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'list': KeyInfo(), + }, + ), ), ('ipv6', 'firewall', 'filter'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-state': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'headers': KeyInfo(can_disable=True), - 'hop-limit': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'reject-with': KeyInfo(), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'reject-with': KeyInfo(), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + }, + ), ), ('ipv6', 'firewall', 'mangle'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-state': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'dst-prefix': KeyInfo(), - 'headers': KeyInfo(can_disable=True), - 'hop-limit': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'new-connection-mark': KeyInfo(), - 'new-dscp': KeyInfo(), - 'new-hop-limit': KeyInfo(), - 'new-mss': KeyInfo(), - 'new-packet-mark': KeyInfo(), - 'new-routing-mark': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'passthrough': KeyInfo(), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'routing-mark': KeyInfo(can_disable=True), - 'sniff-id': KeyInfo(), - 'sniff-target': KeyInfo(), - 'sniff-target-port': KeyInfo(), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'src-prefix': KeyInfo(), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - } + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'dst-prefix': KeyInfo(), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'new-connection-mark': KeyInfo(), + 'new-dscp': KeyInfo(), + 'new-hop-limit': KeyInfo(), + 'new-mss': KeyInfo(), + 'new-packet-mark': KeyInfo(), + 'new-routing-mark': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'passthrough': KeyInfo(), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'sniff-id': KeyInfo(), + 'sniff-target': KeyInfo(), + 'sniff-target-port': KeyInfo(), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'src-prefix': KeyInfo(), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + } + ), ), ('ipv6', 'firewall', 'nat'): APIData( - fully_understood=True, - stratify_keys=('chain', ), - fields={ - 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'connection-bytes': KeyInfo(can_disable=True), - 'connection-limit': KeyInfo(can_disable=True), - 'connection-mark': KeyInfo(can_disable=True), - 'connection-rate': KeyInfo(can_disable=True), - 'connection-state': KeyInfo(can_disable=True), - 'connection-type': KeyInfo(can_disable=True), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'layer7-protocol': KeyInfo(can_disable=True), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'routing-mark': KeyInfo(can_disable=True), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - 'to-addresses': KeyInfo(can_disable=True), - 'to-ports': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain', ), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-bytes': KeyInfo(can_disable=True), + 'connection-limit': KeyInfo(can_disable=True), + 'connection-mark': KeyInfo(can_disable=True), + 'connection-rate': KeyInfo(can_disable=True), + 'connection-state': KeyInfo(can_disable=True), + 'connection-type': KeyInfo(can_disable=True), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'layer7-protocol': KeyInfo(can_disable=True), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + 'to-addresses': KeyInfo(can_disable=True), + 'to-ports': KeyInfo(can_disable=True), + }, + ), ), ('ipv6', 'firewall', 'raw'): APIData( - fully_understood=True, - stratify_keys=('chain',), - fields={ - 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), - 'chain': KeyInfo(), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'dscp': KeyInfo(can_disable=True), - 'dst-address': KeyInfo(can_disable=True), - 'dst-address-list': KeyInfo(can_disable=True), - 'dst-address-type': KeyInfo(can_disable=True), - 'dst-limit': KeyInfo(can_disable=True), - 'dst-port': KeyInfo(can_disable=True), - 'headers': KeyInfo(can_disable=True), - 'hop-limit': KeyInfo(can_disable=True), - 'icmp-options': KeyInfo(can_disable=True), - 'in-bridge-port': KeyInfo(can_disable=True), - 'in-bridge-port-list': KeyInfo(can_disable=True), - 'in-interface': KeyInfo(can_disable=True), - 'in-interface-list': KeyInfo(can_disable=True), - 'ingress-priority': KeyInfo(can_disable=True), - 'ipsec-policy': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), - 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), - 'nth': KeyInfo(can_disable=True), - 'out-bridge-port': KeyInfo(can_disable=True), - 'out-bridge-port-list': KeyInfo(can_disable=True), - 'out-interface': KeyInfo(can_disable=True), - 'out-interface-list': KeyInfo(can_disable=True), - 'packet-mark': KeyInfo(can_disable=True), - 'packet-size': KeyInfo(can_disable=True), - 'per-connection-classifier': KeyInfo(can_disable=True), - 'port': KeyInfo(can_disable=True), - 'priority': KeyInfo(can_disable=True), - 'protocol': KeyInfo(can_disable=True), - 'random': KeyInfo(can_disable=True), - 'src-address': KeyInfo(can_disable=True), - 'src-address-list': KeyInfo(can_disable=True), - 'src-address-type': KeyInfo(can_disable=True), - 'src-mac-address': KeyInfo(can_disable=True), - 'src-port': KeyInfo(can_disable=True), - 'tcp-flags': KeyInfo(can_disable=True), - 'tcp-mss': KeyInfo(can_disable=True), - 'time': KeyInfo(can_disable=True), - 'tls-host': KeyInfo(can_disable=True), - } + unversioned=VersionedAPIData( + fully_understood=True, + stratify_keys=('chain',), + fields={ + 'action': KeyInfo(), + 'address-list': KeyInfo(), + 'address-list-timeout': KeyInfo(), + 'chain': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'content': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'dscp': KeyInfo(can_disable=True), + 'dst-address': KeyInfo(can_disable=True), + 'dst-address-list': KeyInfo(can_disable=True), + 'dst-address-type': KeyInfo(can_disable=True), + 'dst-limit': KeyInfo(can_disable=True), + 'dst-port': KeyInfo(can_disable=True), + 'headers': KeyInfo(can_disable=True), + 'hop-limit': KeyInfo(can_disable=True), + 'icmp-options': KeyInfo(can_disable=True), + 'in-bridge-port': KeyInfo(can_disable=True), + 'in-bridge-port-list': KeyInfo(can_disable=True), + 'in-interface': KeyInfo(can_disable=True), + 'in-interface-list': KeyInfo(can_disable=True), + 'ingress-priority': KeyInfo(can_disable=True), + 'ipsec-policy': KeyInfo(can_disable=True), + 'jump-target': KeyInfo(), + 'limit': KeyInfo(can_disable=True), + 'log': KeyInfo(), + 'log-prefix': KeyInfo(), + 'nth': KeyInfo(can_disable=True), + 'out-bridge-port': KeyInfo(can_disable=True), + 'out-bridge-port-list': KeyInfo(can_disable=True), + 'out-interface': KeyInfo(can_disable=True), + 'out-interface-list': KeyInfo(can_disable=True), + 'packet-mark': KeyInfo(can_disable=True), + 'packet-size': KeyInfo(can_disable=True), + 'per-connection-classifier': KeyInfo(can_disable=True), + 'port': KeyInfo(can_disable=True), + 'priority': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'random': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'src-address-list': KeyInfo(can_disable=True), + 'src-address-type': KeyInfo(can_disable=True), + 'src-mac-address': KeyInfo(can_disable=True), + 'src-port': KeyInfo(can_disable=True), + 'tcp-flags': KeyInfo(can_disable=True), + 'tcp-mss': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'tls-host': KeyInfo(can_disable=True), + } + ), ), ('ipv6', 'nd'): APIData( - fully_understood=True, - primary_keys=('interface', ), - fields={ - 'advertise-dns': KeyInfo(default=True), - 'advertise-mac-address': KeyInfo(default=True), - 'disabled': KeyInfo(default=False), - 'dns': KeyInfo(default=''), - 'hop-limit': KeyInfo(default='unspecified'), - 'interface': KeyInfo(), - 'managed-address-configuration': KeyInfo(default=False), - 'mtu': KeyInfo(default='unspecified'), - 'other-configuration': KeyInfo(default=False), - 'ra-delay': KeyInfo(default='3s'), - 'ra-interval': KeyInfo(default='3m20s-10m'), - 'ra-lifetime': KeyInfo(default='30m'), - 'ra-preference': KeyInfo(default='medium'), - 'reachable-time': KeyInfo(default='unspecified'), - 'retransmit-interval': KeyInfo(default='unspecified'), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'advertise-dns': KeyInfo(default=True), + 'advertise-mac-address': KeyInfo(default=True), + 'disabled': KeyInfo(default=False), + 'dns': KeyInfo(default=''), + 'hop-limit': KeyInfo(default='unspecified'), + 'interface': KeyInfo(), + 'managed-address-configuration': KeyInfo(default=False), + 'mtu': KeyInfo(default='unspecified'), + 'other-configuration': KeyInfo(default=False), + 'ra-delay': KeyInfo(default='3s'), + 'ra-interval': KeyInfo(default='3m20s-10m'), + 'ra-lifetime': KeyInfo(default='30m'), + 'ra-preference': KeyInfo(default='medium'), + 'reachable-time': KeyInfo(default='unspecified'), + 'retransmit-interval': KeyInfo(default='unspecified'), + }, + ), ), ('ipv6', 'nd', 'prefix', 'default'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'autonomous': KeyInfo(default=True), - 'preferred-lifetime': KeyInfo(default='1w'), - 'valid-lifetime': KeyInfo(default='4w2d'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'autonomous': KeyInfo(default=True), + 'preferred-lifetime': KeyInfo(default='1w'), + 'valid-lifetime': KeyInfo(default='4w2d'), + }, + ), ), ('ipv6', 'route'): APIData( - fully_understood=True, - fields={ - 'bgp-as-path': KeyInfo(can_disable=True), - 'bgp-atomic-aggregate': KeyInfo(can_disable=True), - 'bgp-communities': KeyInfo(can_disable=True), - 'bgp-local-pref': KeyInfo(can_disable=True), - 'bgp-med': KeyInfo(can_disable=True), - 'bgp-origin': KeyInfo(can_disable=True), - 'bgp-prepend': KeyInfo(can_disable=True), - 'type': KeyInfo(can_disable=True, remove_value='unicast'), - 'blackhole': KeyInfo(can_disable=True), - 'check-gateway': KeyInfo(can_disable=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(), - 'distance': KeyInfo(default=1), - 'dst-address': KeyInfo(), - 'gateway': KeyInfo(), - 'route-tag': KeyInfo(can_disable=True), - 'routing-table': KeyInfo(default='main'), - 'scope': KeyInfo(default=30), - 'target-scope': KeyInfo(default=10), - 'vrf-interface': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'bgp-as-path': KeyInfo(can_disable=True), + 'bgp-atomic-aggregate': KeyInfo(can_disable=True), + 'bgp-communities': KeyInfo(can_disable=True), + 'bgp-local-pref': KeyInfo(can_disable=True), + 'bgp-med': KeyInfo(can_disable=True), + 'bgp-origin': KeyInfo(can_disable=True), + 'bgp-prepend': KeyInfo(can_disable=True), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'blackhole': KeyInfo(can_disable=True), + 'check-gateway': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(), + 'distance': KeyInfo(default=1), + 'dst-address': KeyInfo(), + 'gateway': KeyInfo(), + 'route-tag': KeyInfo(can_disable=True), + 'routing-table': KeyInfo(default='main'), + 'scope': KeyInfo(default=30), + 'target-scope': KeyInfo(default=10), + 'vrf-interface': KeyInfo(can_disable=True), + }, + ), ), ('mpls', ): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allow-fast-path': KeyInfo(default=True), - 'dynamic-label-range': KeyInfo(default='16-1048575'), - 'propagate-ttl': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allow-fast-path': KeyInfo(default=True), + 'dynamic-label-range': KeyInfo(default='16-1048575'), + 'propagate-ttl': KeyInfo(default=True), + }, + ), ), ('mpls', 'interface'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'interface': KeyInfo(), - 'mpls-mtu': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'interface': KeyInfo(), + 'mpls-mtu': KeyInfo(), + }, + ), ), ('mpls', 'ldp'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'distribute-for-default-route': KeyInfo(default=False), - 'enabled': KeyInfo(default=False), - 'hop-limit': KeyInfo(default=255), - 'loop-detect': KeyInfo(default=False), - 'lsr-id': KeyInfo(default='0.0.0.0'), - 'path-vector-limit': KeyInfo(default=255), - 'transport-address': KeyInfo(default='0.0.0.0'), - 'use-explicit-null': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-for-default-route': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'hop-limit': KeyInfo(default=255), + 'loop-detect': KeyInfo(default=False), + 'lsr-id': KeyInfo(default='0.0.0.0'), + 'path-vector-limit': KeyInfo(default=255), + 'transport-address': KeyInfo(default='0.0.0.0'), + 'use-explicit-null': KeyInfo(default=False), + }, + ), ), ('port', 'firmware'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'directory': KeyInfo(default='firmware'), - 'ignore-directip-modem': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'directory': KeyInfo(default='firmware'), + 'ignore-directip-modem': KeyInfo(default=False), + }, + ), ), ('ppp', 'aaa'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accounting': KeyInfo(default=True), - 'interim-update': KeyInfo(default='0s'), - 'use-circuit-id-in-nas-port-id': KeyInfo(default=False), - 'use-radius': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'interim-update': KeyInfo(default='0s'), + 'use-circuit-id-in-nas-port-id': KeyInfo(default=False), + 'use-radius': KeyInfo(default=False), + }, + ), ), ('radius', 'incoming'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accept': KeyInfo(default=False), - 'port': KeyInfo(default=3799), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accept': KeyInfo(default=False), + 'port': KeyInfo(default=3799), + }, + ), ), ('routing', 'bfd', 'interface'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), - fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'interface': KeyInfo(), - 'interval': KeyInfo(), - 'min-rx': KeyInfo(), - 'multiplier': KeyInfo(), - }, + unversioned=VersionedAPIData( + unknown_mechanism=True, + # primary_keys=('default', ), + fields={ + 'default': KeyInfo(), + 'disabled': KeyInfo(), + 'interface': KeyInfo(), + 'interval': KeyInfo(), + 'min-rx': KeyInfo(), + 'multiplier': KeyInfo(), + }, + ), ), ('routing', 'mme'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'bidirectional-timeout': KeyInfo(default=2), - 'gateway-class': KeyInfo(default='none'), - 'gateway-keepalive': KeyInfo(default='1m'), - 'gateway-selection': KeyInfo(default='no-gateway'), - 'origination-interval': KeyInfo(default='5s'), - 'preferred-gateway': KeyInfo(default='0.0.0.0'), - 'timeout': KeyInfo(default='1m'), - 'ttl': KeyInfo(default=50), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'bidirectional-timeout': KeyInfo(default=2), + 'gateway-class': KeyInfo(default='none'), + 'gateway-keepalive': KeyInfo(default='1m'), + 'gateway-selection': KeyInfo(default='no-gateway'), + 'origination-interval': KeyInfo(default='5s'), + 'preferred-gateway': KeyInfo(default='0.0.0.0'), + 'timeout': KeyInfo(default='1m'), + 'ttl': KeyInfo(default=50), + }, + ), ), ('routing', 'rip'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'distribute-default': KeyInfo(default='never'), - 'garbage-timer': KeyInfo(default='2m'), - 'metric-bgp': KeyInfo(default=1), - 'metric-connected': KeyInfo(default=1), - 'metric-default': KeyInfo(default=1), - 'metric-ospf': KeyInfo(default=1), - 'metric-static': KeyInfo(default=1), - 'redistribute-bgp': KeyInfo(default=False), - 'redistribute-connected': KeyInfo(default=False), - 'redistribute-ospf': KeyInfo(default=False), - 'redistribute-static': KeyInfo(default=False), - 'routing-table': KeyInfo(default='main'), - 'timeout-timer': KeyInfo(default='3m'), - 'update-timer': KeyInfo(default='30s'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-default': KeyInfo(default='never'), + 'garbage-timer': KeyInfo(default='2m'), + 'metric-bgp': KeyInfo(default=1), + 'metric-connected': KeyInfo(default=1), + 'metric-default': KeyInfo(default=1), + 'metric-ospf': KeyInfo(default=1), + 'metric-static': KeyInfo(default=1), + 'redistribute-bgp': KeyInfo(default=False), + 'redistribute-connected': KeyInfo(default=False), + 'redistribute-ospf': KeyInfo(default=False), + 'redistribute-static': KeyInfo(default=False), + 'routing-table': KeyInfo(default='main'), + 'timeout-timer': KeyInfo(default='3m'), + 'update-timer': KeyInfo(default='30s'), + }, + ), ), ('routing', 'ripng'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'distribute-default': KeyInfo(default='never'), - 'garbage-timer': KeyInfo(default='2m'), - 'metric-bgp': KeyInfo(default=1), - 'metric-connected': KeyInfo(default=1), - 'metric-default': KeyInfo(default=1), - 'metric-ospf': KeyInfo(default=1), - 'metric-static': KeyInfo(default=1), - 'redistribute-bgp': KeyInfo(default=False), - 'redistribute-connected': KeyInfo(default=False), - 'redistribute-ospf': KeyInfo(default=False), - 'redistribute-static': KeyInfo(default=False), - 'timeout-timer': KeyInfo(default='3m'), - 'update-timer': KeyInfo(default='30s'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-default': KeyInfo(default='never'), + 'garbage-timer': KeyInfo(default='2m'), + 'metric-bgp': KeyInfo(default=1), + 'metric-connected': KeyInfo(default=1), + 'metric-default': KeyInfo(default=1), + 'metric-ospf': KeyInfo(default=1), + 'metric-static': KeyInfo(default=1), + 'redistribute-bgp': KeyInfo(default=False), + 'redistribute-connected': KeyInfo(default=False), + 'redistribute-ospf': KeyInfo(default=False), + 'redistribute-static': KeyInfo(default=False), + 'timeout-timer': KeyInfo(default='3m'), + 'update-timer': KeyInfo(default='30s'), + }, + ), ), ('snmp', ): APIData( - single_value=True, - fully_understood=True, - fields={ - 'contact': KeyInfo(default=''), - 'enabled': KeyInfo(default=False), - 'engine-id': KeyInfo(default=''), - 'engine-id-suffix': KeyInfo(default=''), - 'location': KeyInfo(default=''), - 'src-address': KeyInfo(default='::'), - 'trap-community': KeyInfo(default='public'), - 'trap-generators': KeyInfo(default='temp-exception'), - 'trap-target': KeyInfo(default=''), - 'trap-version': KeyInfo(default=1), - 'trap-interfaces': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'contact': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'engine-id': KeyInfo(default=''), + 'engine-id-suffix': KeyInfo(default=''), + 'location': KeyInfo(default=''), + 'src-address': KeyInfo(default='::'), + 'trap-community': KeyInfo(default='public'), + 'trap-generators': KeyInfo(default='temp-exception'), + 'trap-target': KeyInfo(default=''), + 'trap-version': KeyInfo(default=1), + 'trap-interfaces': KeyInfo(default=''), + }, + ), ), ('system', 'clock'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'date': KeyInfo(), - 'gmt-offset': KeyInfo(), - 'time': KeyInfo(), - 'time-zone-autodetect': KeyInfo(default=True), - 'time-zone-name': KeyInfo(default='manual'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'date': KeyInfo(), + 'gmt-offset': KeyInfo(), + 'time': KeyInfo(), + 'time-zone-autodetect': KeyInfo(default=True), + 'time-zone-name': KeyInfo(default='manual'), + }, + ), ), ('system', 'clock', 'manual'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'dst-delta': KeyInfo(default='00:00'), - 'dst-end': KeyInfo(default='jan/01/1970 00:00:00'), - 'dst-start': KeyInfo(default='jan/01/1970 00:00:00'), - 'time-zone': KeyInfo(default='+00:00'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'dst-delta': KeyInfo(default='00:00'), + 'dst-end': KeyInfo(default='jan/01/1970 00:00:00'), + 'dst-start': KeyInfo(default='jan/01/1970 00:00:00'), + 'time-zone': KeyInfo(default='+00:00'), + }, + ), ), ('system', 'identity'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'name': KeyInfo(default='Mikrotik'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'name': KeyInfo(default='Mikrotik'), + }, + ), ), ('system', 'leds', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'all-leds-off': KeyInfo(default='never'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'all-leds-off': KeyInfo(default='never'), + }, + ), ), ('system', 'note'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'note': KeyInfo(default=''), - 'show-at-login': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'note': KeyInfo(default=''), + 'show-at-login': KeyInfo(default=True), + }, + ), ), ('system', 'ntp', 'client'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'enabled': KeyInfo(default=False), - 'primary-ntp': KeyInfo(default='0.0.0.0'), - 'secondary-ntp': KeyInfo(default='0.0.0.0'), - 'server-dns-names': KeyInfo(default=''), - 'servers': KeyInfo(default=''), - 'mode': KeyInfo(default='unicast'), - 'vrf': KeyInfo(default='main'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=False), + 'primary-ntp': KeyInfo(default='0.0.0.0'), + 'secondary-ntp': KeyInfo(default='0.0.0.0'), + 'server-dns-names': KeyInfo(default=''), + 'servers': KeyInfo(default=''), + 'mode': KeyInfo(default='unicast'), + 'vrf': KeyInfo(default='main'), + }, + ), ), ('system', 'ntp', 'client', 'servers'): APIData( - primary_keys=('address', ), - fully_understood=True, - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'address': KeyInfo(), - 'auth-key': KeyInfo(default='none'), - 'iburst': KeyInfo(default=True), - 'max-poll': KeyInfo(default=10), - 'min-poll': KeyInfo(default=6), - }, + unversioned=VersionedAPIData( + primary_keys=('address', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'address': KeyInfo(), + 'auth-key': KeyInfo(default='none'), + 'iburst': KeyInfo(default=True), + 'max-poll': KeyInfo(default=10), + 'min-poll': KeyInfo(default=6), + }, + ), ), ('system', 'ntp', 'server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'auth-key': KeyInfo(default='none'), - 'broadcast': KeyInfo(default=False), - 'broadcast-addresses': KeyInfo(default=''), - 'enabled': KeyInfo(default=False), - 'local-clock-stratum': KeyInfo(default=5), - 'manycast': KeyInfo(default=False), - 'multicast': KeyInfo(default=False), - 'use-local-clock': KeyInfo(default=False), - 'vrf': KeyInfo(default='main'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auth-key': KeyInfo(default='none'), + 'broadcast': KeyInfo(default=False), + 'broadcast-addresses': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'local-clock-stratum': KeyInfo(default=5), + 'manycast': KeyInfo(default=False), + 'multicast': KeyInfo(default=False), + 'use-local-clock': KeyInfo(default=False), + 'vrf': KeyInfo(default='main'), + }, + ), ), ('system', 'package', 'update'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'channel': KeyInfo(default='stable'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'channel': KeyInfo(default='stable'), + }, + ), ), ('system', 'routerboard', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'auto-upgrade': KeyInfo(default=False), - 'baud-rate': KeyInfo(default=115200), - 'boot-delay': KeyInfo(default='2s'), - 'boot-device': KeyInfo(default='nand-if-fail-then-ethernet'), - 'boot-protocol': KeyInfo(default='bootp'), - 'enable-jumper-reset': KeyInfo(default=True), - 'enter-setup-on': KeyInfo(default='any-key'), - 'force-backup-booter': KeyInfo(default=False), - 'protected-routerboot': KeyInfo(default='disabled'), - 'reformat-hold-button': KeyInfo(default='20s'), - 'reformat-hold-button-max': KeyInfo(default='10m'), - 'silent-boot': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auto-upgrade': KeyInfo(default=False), + 'baud-rate': KeyInfo(default=115200), + 'boot-delay': KeyInfo(default='2s'), + 'boot-device': KeyInfo(default='nand-if-fail-then-ethernet'), + 'boot-protocol': KeyInfo(default='bootp'), + 'enable-jumper-reset': KeyInfo(default=True), + 'enter-setup-on': KeyInfo(default='any-key'), + 'force-backup-booter': KeyInfo(default=False), + 'protected-routerboot': KeyInfo(default='disabled'), + 'reformat-hold-button': KeyInfo(default='20s'), + 'reformat-hold-button-max': KeyInfo(default='10m'), + 'silent-boot': KeyInfo(default=False), + }, + ), ), ('system', 'upgrade', 'mirror'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'check-interval': KeyInfo(default='1d'), - 'enabled': KeyInfo(default=False), - 'primary-server': KeyInfo(default='0.0.0.0'), - 'secondary-server': KeyInfo(default='0.0.0.0'), - 'user': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'check-interval': KeyInfo(default='1d'), + 'enabled': KeyInfo(default=False), + 'primary-server': KeyInfo(default='0.0.0.0'), + 'secondary-server': KeyInfo(default='0.0.0.0'), + 'user': KeyInfo(default=''), + }, + ), ), ('system', 'ups'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'alarm-setting': KeyInfo(default='immediate'), - 'check-capabilities': KeyInfo(can_disable=True, remove_value=True), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=True), - 'min-runtime': KeyInfo(default='never'), - 'name': KeyInfo(), - 'offline-time': KeyInfo(default='0s'), - 'port': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'alarm-setting': KeyInfo(default='immediate'), + 'check-capabilities': KeyInfo(can_disable=True, remove_value=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=True), + 'min-runtime': KeyInfo(default='never'), + 'name': KeyInfo(), + 'offline-time': KeyInfo(default='0s'), + 'port': KeyInfo(required=True), + }, + ), ), ('system', 'watchdog'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'auto-send-supout': KeyInfo(default=False), - 'automatic-supout': KeyInfo(default=True), - 'ping-start-after-boot': KeyInfo(default='5m'), - 'ping-timeout': KeyInfo(default='1m'), - 'watch-address': KeyInfo(default='none'), - 'watchdog-timer': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auto-send-supout': KeyInfo(default=False), + 'automatic-supout': KeyInfo(default=True), + 'ping-start-after-boot': KeyInfo(default='5m'), + 'ping-timeout': KeyInfo(default='1m'), + 'watch-address': KeyInfo(default='none'), + 'watchdog-timer': KeyInfo(default=True), + }, + ), ), ('tool', 'bandwidth-server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allocate-udp-ports-from': KeyInfo(default=2000), - 'authenticate': KeyInfo(default=True), - 'enabled': KeyInfo(default=True), - 'max-sessions': KeyInfo(default=100), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allocate-udp-ports-from': KeyInfo(default=2000), + 'authenticate': KeyInfo(default=True), + 'enabled': KeyInfo(default=True), + 'max-sessions': KeyInfo(default=100), + }, + ), ), ('tool', 'e-mail'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'address': KeyInfo(default='0.0.0.0'), - 'from': KeyInfo(default='<>'), - 'password': KeyInfo(default=''), - 'port': KeyInfo(default=25), - 'start-tls': KeyInfo(default=False), - 'tls': KeyInfo(default=False), - 'user': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'address': KeyInfo(default='0.0.0.0'), + 'from': KeyInfo(default='<>'), + 'password': KeyInfo(default=''), + 'port': KeyInfo(default=25), + 'start-tls': KeyInfo(default=False), + 'tls': KeyInfo(default=False), + 'user': KeyInfo(default=''), + }, + ), ), ('tool', 'graphing'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'page-refresh': KeyInfo(default=300), - 'store-every': KeyInfo(default='5min'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'page-refresh': KeyInfo(default=300), + 'store-every': KeyInfo(default='5min'), + }, + ), ), ('tool', 'mac-server'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allowed-interface-list': KeyInfo(), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-interface-list': KeyInfo(), + }, + ), ), ('tool', 'mac-server', 'mac-winbox'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allowed-interface-list': KeyInfo(), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-interface-list': KeyInfo(), + }, + ), ), ('tool', 'mac-server', 'ping'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'enabled': KeyInfo(default=True), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=True), + }, + ), ), ('tool', 'romon'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'enabled': KeyInfo(default=False), - 'id': KeyInfo(default='00:00:00:00:00:00'), - 'secrets': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'enabled': KeyInfo(default=False), + 'id': KeyInfo(default='00:00:00:00:00:00'), + 'secrets': KeyInfo(default=''), + }, + ), ), ('tool', 'romon', 'port'): APIData( - fields={ - 'cost': KeyInfo(), - 'disabled': KeyInfo(), - 'forbid': KeyInfo(), - 'interface': KeyInfo(), - 'secrets': KeyInfo(), - }, + unversioned=VersionedAPIData( + fields={ + 'cost': KeyInfo(), + 'disabled': KeyInfo(), + 'forbid': KeyInfo(), + 'interface': KeyInfo(), + 'secrets': KeyInfo(), + }, + ), ), ('tool', 'sms'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'allowed-number': KeyInfo(default=''), - 'auto-erase': KeyInfo(default=False), - 'channel': KeyInfo(default=0), - 'port': KeyInfo(default='none'), - 'receive-enabled': KeyInfo(default=False), - 'secret': KeyInfo(default=''), - 'sim-pin': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'allowed-number': KeyInfo(default=''), + 'auto-erase': KeyInfo(default=False), + 'channel': KeyInfo(default=0), + 'port': KeyInfo(default='none'), + 'receive-enabled': KeyInfo(default=False), + 'secret': KeyInfo(default=''), + 'sim-pin': KeyInfo(default=''), + }, + ), ), ('tool', 'sniffer'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'file-limit': KeyInfo(default='1000KiB'), - 'file-name': KeyInfo(default=''), - 'filter-cpu': KeyInfo(default=''), - 'filter-direction': KeyInfo(default='any'), - 'filter-interface': KeyInfo(default=''), - 'filter-ip-address': KeyInfo(default=''), - 'filter-ip-protocol': KeyInfo(default=''), - 'filter-ipv6-address': KeyInfo(default=''), - 'filter-mac-address': KeyInfo(default=''), - 'filter-mac-protocol': KeyInfo(default=''), - 'filter-operator-between-entries': KeyInfo(default='or'), - 'filter-port': KeyInfo(default=''), - 'filter-size': KeyInfo(default=''), - 'filter-stream': KeyInfo(default=False), - 'memory-limit': KeyInfo(default='100KiB'), - 'memory-scroll': KeyInfo(default=True), - 'only-headers': KeyInfo(default=False), - 'streaming-enabled': KeyInfo(default=False), - 'streaming-server': KeyInfo(default='0.0.0.0:37008'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'file-limit': KeyInfo(default='1000KiB'), + 'file-name': KeyInfo(default=''), + 'filter-cpu': KeyInfo(default=''), + 'filter-direction': KeyInfo(default='any'), + 'filter-interface': KeyInfo(default=''), + 'filter-ip-address': KeyInfo(default=''), + 'filter-ip-protocol': KeyInfo(default=''), + 'filter-ipv6-address': KeyInfo(default=''), + 'filter-mac-address': KeyInfo(default=''), + 'filter-mac-protocol': KeyInfo(default=''), + 'filter-operator-between-entries': KeyInfo(default='or'), + 'filter-port': KeyInfo(default=''), + 'filter-size': KeyInfo(default=''), + 'filter-stream': KeyInfo(default=False), + 'memory-limit': KeyInfo(default='100KiB'), + 'memory-scroll': KeyInfo(default=True), + 'only-headers': KeyInfo(default=False), + 'streaming-enabled': KeyInfo(default=False), + 'streaming-server': KeyInfo(default='0.0.0.0:37008'), + }, + ), ), ('tool', 'traffic-generator'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'latency-distribution-max': KeyInfo(default='100us'), - 'measure-out-of-order': KeyInfo(default=True), - 'stats-samples-to-keep': KeyInfo(default=100), - 'test-id': KeyInfo(default=0), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'latency-distribution-max': KeyInfo(default='100us'), + 'measure-out-of-order': KeyInfo(default=True), + 'stats-samples-to-keep': KeyInfo(default=100), + 'test-id': KeyInfo(default=0), + }, + ), ), ('user', 'aaa'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'accounting': KeyInfo(default=True), - 'default-group': KeyInfo(default='read'), - 'exclude-groups': KeyInfo(default=''), - 'interim-update': KeyInfo(default='0s'), - 'use-radius': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'accounting': KeyInfo(default=True), + 'default-group': KeyInfo(default='read'), + 'exclude-groups': KeyInfo(default=''), + 'interim-update': KeyInfo(default='0s'), + 'use-radius': KeyInfo(default=False), + }, + ), ), ('user', 'settings'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'minimum-categories': KeyInfo(), - 'minimum-password-length': KeyInfo(), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'minimum-categories': KeyInfo(), + 'minimum-password-length': KeyInfo(), + }, + ), ), ('queue', 'interface'): APIData( - primary_keys=('interface', ), - fully_understood=True, - fixed_entries=True, - fields={ - 'interface': KeyInfo(required=True), - 'queue': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + primary_keys=('interface', ), + fully_understood=True, + fixed_entries=True, + fields={ + 'interface': KeyInfo(required=True), + 'queue': KeyInfo(required=True), + }, + ), ), ('queue', 'tree'): APIData( - primary_keys=('name', ), - fully_understood=True, - fields={ - 'bucket-size': KeyInfo(default='0.1'), - 'burst-limit': KeyInfo(default=0), - 'burst-threshold': KeyInfo(default=0), - 'burst-time': KeyInfo(default='0s'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'limit-at': KeyInfo(default=0), - 'max-limit': KeyInfo(default=0), - 'name': KeyInfo(), - 'packet-mark': KeyInfo(default=''), - 'parent': KeyInfo(required=True), - 'priority': KeyInfo(default=8), - 'queue': KeyInfo(default='default-small'), - }, + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'bucket-size': KeyInfo(default='0.1'), + 'burst-limit': KeyInfo(default=0), + 'burst-threshold': KeyInfo(default=0), + 'burst-time': KeyInfo(default='0s'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'limit-at': KeyInfo(default=0), + 'max-limit': KeyInfo(default=0), + 'name': KeyInfo(), + 'packet-mark': KeyInfo(default=''), + 'parent': KeyInfo(required=True), + 'priority': KeyInfo(default=8), + 'queue': KeyInfo(default='default-small'), + }, + ), ), ('interface', 'ethernet', 'switch'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'cpu-flow-control': KeyInfo(default=True), - 'mirror-source': KeyInfo(default='none'), - 'mirror-target': KeyInfo(default='none'), - 'name': KeyInfo(), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'cpu-flow-control': KeyInfo(default=True), + 'mirror-source': KeyInfo(default='none'), + 'mirror-target': KeyInfo(default='none'), + 'name': KeyInfo(), + }, + ), ), ('interface', 'ethernet', 'switch', 'port'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'default-vlan-id': KeyInfo(), - 'name': KeyInfo(), - 'vlan-header': KeyInfo(default='leave-as-is'), - 'vlan-mode': KeyInfo(default='disabled'), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'default-vlan-id': KeyInfo(), + 'name': KeyInfo(), + 'vlan-header': KeyInfo(default='leave-as-is'), + 'vlan-mode': KeyInfo(default='disabled'), + }, + ), ), ('ip', 'dhcp-client', 'option'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'code': KeyInfo(), - 'name': KeyInfo(), - 'value': KeyInfo(), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'code': KeyInfo(), + 'name': KeyInfo(), + 'value': KeyInfo(), + }, + ), ), ('ppp', 'profile'): APIData( - has_identifier=True, - fields={ - 'address-list': KeyInfo(), - 'bridge': KeyInfo(can_disable=True), - 'bridge-horizon': KeyInfo(can_disable=True), - 'bridge-learning': KeyInfo(), - 'bridge-path-cost': KeyInfo(can_disable=True), - 'bridge-port-priority': KeyInfo(can_disable=True), - 'change-tcp-mss': KeyInfo(), - 'dns-server': KeyInfo(can_disable=True), - 'idle-timeout': KeyInfo(can_disable=True), - 'incoming-filter': KeyInfo(can_disable=True), - 'insert-queue-before': KeyInfo(can_disable=True), - 'interface-list': KeyInfo(can_disable=True), - 'local-address': KeyInfo(can_disable=True), - 'name': KeyInfo(), - 'on-down': KeyInfo(), - 'on-up': KeyInfo(), - 'only-one': KeyInfo(), - 'outgoing-filter': KeyInfo(can_disable=True), - 'parent-queue': KeyInfo(can_disable=True), - 'queue-type': KeyInfo(can_disable=True), - 'rate-limit': KeyInfo(can_disable=True), - 'remote-address': KeyInfo(can_disable=True), - 'session-timeout': KeyInfo(can_disable=True), - 'use-compression': KeyInfo(), - 'use-encryption': KeyInfo(), - 'use-ipv6': KeyInfo(), - 'use-mpls': KeyInfo(), - 'use-upnp': KeyInfo(), - 'wins-server': KeyInfo(can_disable=True), - }, + unversioned=VersionedAPIData( + has_identifier=True, + fields={ + 'address-list': KeyInfo(), + 'bridge': KeyInfo(can_disable=True), + 'bridge-horizon': KeyInfo(can_disable=True), + 'bridge-learning': KeyInfo(), + 'bridge-path-cost': KeyInfo(can_disable=True), + 'bridge-port-priority': KeyInfo(can_disable=True), + 'change-tcp-mss': KeyInfo(), + 'dns-server': KeyInfo(can_disable=True), + 'idle-timeout': KeyInfo(can_disable=True), + 'incoming-filter': KeyInfo(can_disable=True), + 'insert-queue-before': KeyInfo(can_disable=True), + 'interface-list': KeyInfo(can_disable=True), + 'local-address': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'on-down': KeyInfo(), + 'on-up': KeyInfo(), + 'only-one': KeyInfo(), + 'outgoing-filter': KeyInfo(can_disable=True), + 'parent-queue': KeyInfo(can_disable=True), + 'queue-type': KeyInfo(can_disable=True), + 'rate-limit': KeyInfo(can_disable=True), + 'remote-address': KeyInfo(can_disable=True), + 'session-timeout': KeyInfo(can_disable=True), + 'use-compression': KeyInfo(), + 'use-encryption': KeyInfo(), + 'use-ipv6': KeyInfo(), + 'use-mpls': KeyInfo(), + 'use-upnp': KeyInfo(), + 'wins-server': KeyInfo(can_disable=True), + }, + ), ), ('queue', 'type'): APIData( - has_identifier=True, - fields={ - 'kind': KeyInfo(), - 'mq-pfifo-limit': KeyInfo(), - 'name': KeyInfo(), - 'pcq-burst-rate': KeyInfo(), - 'pcq-burst-threshold': KeyInfo(), - 'pcq-burst-time': KeyInfo(), - 'pcq-classifier': KeyInfo(), - 'pcq-dst-address-mask': KeyInfo(), - 'pcq-dst-address6-mask': KeyInfo(), - 'pcq-limit': KeyInfo(), - 'pcq-rate': KeyInfo(), - 'pcq-src-address-mask': KeyInfo(), - 'pcq-src-address6-mask': KeyInfo(), - 'pcq-total-limit': KeyInfo(), - 'pfifo-limit': KeyInfo(), - 'red-avg-packet': KeyInfo(), - 'red-burst': KeyInfo(), - 'red-limit': KeyInfo(), - 'red-max-threshold': KeyInfo(), - 'red-min-threshold': KeyInfo(), - 'sfq-allot': KeyInfo(), - 'sfq-perturb': KeyInfo(), - }, + unversioned=VersionedAPIData( + has_identifier=True, + fields={ + 'kind': KeyInfo(), + 'mq-pfifo-limit': KeyInfo(), + 'name': KeyInfo(), + 'pcq-burst-rate': KeyInfo(), + 'pcq-burst-threshold': KeyInfo(), + 'pcq-burst-time': KeyInfo(), + 'pcq-classifier': KeyInfo(), + 'pcq-dst-address-mask': KeyInfo(), + 'pcq-dst-address6-mask': KeyInfo(), + 'pcq-limit': KeyInfo(), + 'pcq-rate': KeyInfo(), + 'pcq-src-address-mask': KeyInfo(), + 'pcq-src-address6-mask': KeyInfo(), + 'pcq-total-limit': KeyInfo(), + 'pfifo-limit': KeyInfo(), + 'red-avg-packet': KeyInfo(), + 'red-burst': KeyInfo(), + 'red-limit': KeyInfo(), + 'red-max-threshold': KeyInfo(), + 'red-min-threshold': KeyInfo(), + 'sfq-allot': KeyInfo(), + 'sfq-perturb': KeyInfo(), + }, + ), ), ('routing', 'bgp', 'instance'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'as': KeyInfo(), - 'client-to-client-reflection': KeyInfo(), - 'cluster-id': KeyInfo(can_disable=True), - 'confederation': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), - 'ignore-as-path-len': KeyInfo(), - 'name': KeyInfo(), - 'out-filter': KeyInfo(), - 'redistribute-connected': KeyInfo(), - 'redistribute-ospf': KeyInfo(), - 'redistribute-other-bgp': KeyInfo(), - 'redistribute-rip': KeyInfo(), - 'redistribute-static': KeyInfo(), - 'router-id': KeyInfo(), - 'routing-table': KeyInfo(), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'as': KeyInfo(), + 'client-to-client-reflection': KeyInfo(), + 'cluster-id': KeyInfo(can_disable=True), + 'confederation': KeyInfo(can_disable=True), + 'disabled': KeyInfo(), + 'ignore-as-path-len': KeyInfo(), + 'name': KeyInfo(), + 'out-filter': KeyInfo(), + 'redistribute-connected': KeyInfo(), + 'redistribute-ospf': KeyInfo(), + 'redistribute-other-bgp': KeyInfo(), + 'redistribute-rip': KeyInfo(), + 'redistribute-static': KeyInfo(), + 'router-id': KeyInfo(), + 'routing-table': KeyInfo(), + }, + ), ), ('system', 'logging', 'action'): APIData( - fully_understood=True, - primary_keys=('name',), - fields={ - 'bsd-syslog': KeyInfo(default=False), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disk-file-count': KeyInfo(default=2), - 'disk-file-name': KeyInfo(default='log'), - 'disk-lines-per-file': KeyInfo(default=1000), - 'disk-stop-on-full': KeyInfo(default=False), - 'email-start-tls': KeyInfo(default=False), - 'email-to': KeyInfo(default=''), - 'memory-lines': KeyInfo(default=1000), - 'memory-stop-on-full': KeyInfo(default=False), - 'name': KeyInfo(), - 'remember': KeyInfo(default=True), - 'remote': KeyInfo(default='0.0.0.0'), - 'remote-port': KeyInfo(default=514), - 'src-address': KeyInfo(default='0.0.0.0'), - 'syslog-facility': KeyInfo(default='daemon'), - 'syslog-severity': KeyInfo(default='auto'), - 'syslog-time-format': KeyInfo(default='bsd-syslog'), - 'target': KeyInfo(required=True), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'bsd-syslog': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disk-file-count': KeyInfo(default=2), + 'disk-file-name': KeyInfo(default='log'), + 'disk-lines-per-file': KeyInfo(default=1000), + 'disk-stop-on-full': KeyInfo(default=False), + 'email-start-tls': KeyInfo(default=False), + 'email-to': KeyInfo(default=''), + 'memory-lines': KeyInfo(default=1000), + 'memory-stop-on-full': KeyInfo(default=False), + 'name': KeyInfo(), + 'remember': KeyInfo(default=True), + 'remote': KeyInfo(default='0.0.0.0'), + 'remote-port': KeyInfo(default=514), + 'src-address': KeyInfo(default='0.0.0.0'), + 'syslog-facility': KeyInfo(default='daemon'), + 'syslog-severity': KeyInfo(default='auto'), + 'syslog-time-format': KeyInfo(default='bsd-syslog'), + 'target': KeyInfo(required=True), + }, + ), ), ('user', 'group'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'name': KeyInfo(), - 'policy': KeyInfo(), - 'skin': KeyInfo(default='default'), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'name': KeyInfo(), + 'policy': KeyInfo(), + 'skin': KeyInfo(default='default'), + }, + ), ), ('caps-man', 'manager'): APIData( - single_value=True, - fully_understood=True, - fields={ - 'ca-certificate': KeyInfo(default='none'), - 'certificate': KeyInfo(default='none'), - 'enabled': KeyInfo(default=False), - 'package-path': KeyInfo(default=''), - 'require-peer-certificate': KeyInfo(default=False), - 'upgrade-policy': KeyInfo(default='none'), - }, + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'ca-certificate': KeyInfo(default='none'), + 'certificate': KeyInfo(default='none'), + 'enabled': KeyInfo(default=False), + 'package-path': KeyInfo(default=''), + 'require-peer-certificate': KeyInfo(default=False), + 'upgrade-policy': KeyInfo(default='none'), + }, + ), ), ('ip', 'firewall', 'service-port'): APIData( - primary_keys=('name', ), - fully_understood=True, - fields={ - 'disabled': KeyInfo(default=False), - 'name': KeyInfo(), - 'ports': KeyInfo(), - 'sip-direct-media': KeyInfo(), - 'sip-timeout': KeyInfo(), - }, + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'ports': KeyInfo(), + 'sip-direct-media': KeyInfo(), + 'sip-timeout': KeyInfo(), + }, + ), ), ('ip', 'firewall', 'layer7-protocol'): APIData( - primary_keys=('name', ), - fully_understood=True, - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'name': KeyInfo(), - 'regexp': KeyInfo(), - }, + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'name': KeyInfo(), + 'regexp': KeyInfo(), + }, + ), ), ('ip', 'hotspot', 'service-port'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'disabled': KeyInfo(default=False), - 'name': KeyInfo(), - 'ports': KeyInfo(), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'ports': KeyInfo(), + }, + ), ), ('ip', 'ipsec', 'policy'): APIData( - fully_understood=True, - fields={ - 'action': KeyInfo(default='encrypt'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'dst-address': KeyInfo(), - 'dst-port': KeyInfo(default='any'), - 'group': KeyInfo(can_disable=True, remove_value='default'), - 'ipsec-protocols': KeyInfo(default='esp'), - 'level': KeyInfo(default='require'), - 'peer': KeyInfo(), - 'proposal': KeyInfo(default='default'), - 'protocol': KeyInfo(default='all'), - 'src-address': KeyInfo(), - 'src-port': KeyInfo(default='any'), - 'template': KeyInfo(can_disable=True, remove_value=False), - # the tepmlate field can't really be changed once the item is created. This config captures the behavior best as it can - # i.e. tepmplate=yes is shown, tepmlate=no is hidden - 'tunnel': KeyInfo(default=False), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='encrypt'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dst-address': KeyInfo(), + 'dst-port': KeyInfo(default='any'), + 'group': KeyInfo(can_disable=True, remove_value='default'), + 'ipsec-protocols': KeyInfo(default='esp'), + 'level': KeyInfo(default='require'), + 'peer': KeyInfo(), + 'proposal': KeyInfo(default='default'), + 'protocol': KeyInfo(default='all'), + 'src-address': KeyInfo(), + 'src-port': KeyInfo(default='any'), + 'template': KeyInfo(can_disable=True, remove_value=False), + # the tepmlate field can't really be changed once the item is created. This config captures the behavior best as it can + # i.e. tepmplate=yes is shown, tepmlate=no is hidden + 'tunnel': KeyInfo(default=False), + }, + ), ), ('ip', 'service'): APIData( - fixed_entries=True, - primary_keys=('name', ), - fully_understood=True, - fields={ - 'address': KeyInfo(), - 'certificate': KeyInfo(), - 'disabled': KeyInfo(default=False), - 'name': KeyInfo(), - 'port': KeyInfo(), - 'tls-version': KeyInfo(), - }, + unversioned=VersionedAPIData( + fixed_entries=True, + primary_keys=('name', ), + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'certificate': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'port': KeyInfo(), + 'tls-version': KeyInfo(), + }, + ), ), ('system', 'logging'): APIData( - fully_understood=True, - fields={ - 'action': KeyInfo(default='memory'), - 'disabled': KeyInfo(default=False), - 'prefix': KeyInfo(default=''), - 'topics': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='memory'), + 'disabled': KeyInfo(default=False), + 'prefix': KeyInfo(default=''), + 'topics': KeyInfo(default=''), + }, + ), ), ('system', 'resource', 'irq'): APIData( - has_identifier=True, - fields={ - 'cpu': KeyInfo(), - }, + unversioned=VersionedAPIData( + has_identifier=True, + fields={ + 'cpu': KeyInfo(), + }, + ), ), ('system', 'scheduler'): APIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interval': KeyInfo(default='0s'), - 'name': KeyInfo(), - 'on-event': KeyInfo(default=''), - 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), - 'start-date': KeyInfo(), - 'start-time': KeyInfo(), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interval': KeyInfo(default='0s'), + 'name': KeyInfo(), + 'on-event': KeyInfo(default=''), + 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), + 'start-date': KeyInfo(), + 'start-time': KeyInfo(), + }, + ), ), ('system', 'script'): APIData( - fully_understood=True, - primary_keys=('name',), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'dont-require-permissions': KeyInfo(default=False), - 'name': KeyInfo(), - 'owner': KeyInfo(), - 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), - 'source': KeyInfo(default=''), - }, + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dont-require-permissions': KeyInfo(default=False), + 'name': KeyInfo(), + 'owner': KeyInfo(), + 'policy': KeyInfo(default='ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon'), + 'source': KeyInfo(default=''), + }, + ), ), } diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 5c598f3..6c276d7 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -97,6 +97,7 @@ def _ros_api_connect(module, username, password, host, port, use_tls, force_no_c def create_api(module): + """Create an API object.""" return _ros_api_connect( module, module.params['username'], @@ -111,3 +112,9 @@ def create_api(module): module.params['encoding'], module.params['timeout'], ) + + +def get_api_version(api): + """Given an API object, query the system's version.""" + system_info = list(api.path().join('system', 'resource'))[0] + return system_info['version'].split(' ', 1)[0] diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 165c0db..787acfc 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -282,6 +282,7 @@ from ansible_collections.community.routeros.plugins.module_utils.api import ( api_argument_spec, check_has_library, create_api, + get_api_version, ) from ansible_collections.community.routeros.plugins.module_utils._api_data import ( @@ -324,9 +325,14 @@ def main(): api = create_api(module) path = split_path(module.params['path']) - path_info = PATHS.get(tuple(path)) - if path_info is None: + versioned_path_info = PATHS.get(tuple(path)) + if versioned_path_info is None: module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) + if versioned_path_info.needs_version: + api_version = get_api_version(api) + if not versioned_path_info.provide_version(api_version): + module.fail_json(msg='Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)) + path_info = versioned_path_info.get_data() handle_disabled = module.params['handle_disabled'] hide_defaults = module.params['hide_defaults'] diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 8e6123a..308b98c 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -331,6 +331,7 @@ from ansible_collections.community.routeros.plugins.module_utils.api import ( api_argument_spec, check_has_library, create_api, + get_api_version, ) from ansible_collections.community.routeros.plugins.module_utils._api_data import ( @@ -1003,8 +1004,23 @@ def get_backend(path_info): return None +def has_backend(versioned_path_info): + if not versioned_path_info.fully_understood: + return False + + if versioned_path_info.unversioned is not None: + return get_backend(versioned_path_info.unversioned) is not None + + if versioned_path_info.versioned is not None: + for dummy, dummy, unversioned in versioned_path_info.versioned: + if get_backend(unversioned) is not None: + return True + + return False + + def main(): - path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if get_backend(path_info) is not None]) + path_choices = sorted([join_path(path) for path, versioned_path_info in PATHS.items() if has_backend(versioned_path_info)]) module_args = dict( path=dict(type='str', required=True, choices=path_choices), data=dict(type='list', elements='dict', required=True), @@ -1029,7 +1045,13 @@ def main(): api = create_api(module) path = split_path(module.params['path']) - path_info = PATHS.get(tuple(path)) + versioned_path_info = PATHS.get(tuple(path)) + if versioned_path_info.needs_version: + api_version = get_api_version(api) + if not versioned_path_info.provide_version(api_version): + module.fail_json(msg='Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)) + path_info = versioned_path_info.get_data() + backend = get_backend(path_info) if path_info is None or backend is None: module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 1250fda..2dfe8cd 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -10,7 +10,7 @@ __metaclass__ = type import pytest from ansible_collections.community.routeros.plugins.module_utils._api_data import ( - APIData, + VersionedAPIData, KeyInfo, split_path, join_path, @@ -19,7 +19,7 @@ from ansible_collections.community.routeros.plugins.module_utils._api_data impor def test_api_data_errors(): with pytest.raises(ValueError) as exc: - APIData() + VersionedAPIData() assert exc.value.args[0] == 'fields must be provided' values = [ @@ -33,39 +33,39 @@ def test_api_data_errors(): for index, (param, param_value) in enumerate(values): for param2, param2_value in values[index + 1:]: with pytest.raises(ValueError) as exc: - APIData(**{param: param_value, param2: param2_value}) + VersionedAPIData(**{param: param_value, param2: param2_value}) assert exc.value.args[0] == 'primary_keys, stratify_keys, has_identifier, single_value, and unknown_mechanism are mutually exclusive' with pytest.raises(ValueError) as exc: - APIData(unknown_mechanism=True, fully_understood=True) + VersionedAPIData(unknown_mechanism=True, fully_understood=True) assert exc.value.args[0] == 'unknown_mechanism and fully_understood cannot be combined' with pytest.raises(ValueError) as exc: - APIData(unknown_mechanism=True, fixed_entries=True) + VersionedAPIData(unknown_mechanism=True, fixed_entries=True) assert exc.value.args[0] == 'fixed_entries can only be used with primary_keys' with pytest.raises(ValueError) as exc: - APIData(primary_keys=['foo'], fields={}) + VersionedAPIData(primary_keys=['foo'], fields={}) assert exc.value.args[0] == 'Primary key foo must be in fields!' with pytest.raises(ValueError) as exc: - APIData(stratify_keys=['foo'], fields={}) + VersionedAPIData(stratify_keys=['foo'], fields={}) assert exc.value.args[0] == 'Stratify key foo must be in fields!' with pytest.raises(ValueError) as exc: - APIData(required_one_of=['foo'], fields={}) + VersionedAPIData(required_one_of=['foo'], fields={}) assert exc.value.args[0] == 'Require one of element at index #1 must be a list!' with pytest.raises(ValueError) as exc: - APIData(required_one_of=[['foo']], fields={}) + VersionedAPIData(required_one_of=[['foo']], fields={}) assert exc.value.args[0] == 'Require one of key foo must be in fields!' with pytest.raises(ValueError) as exc: - APIData(mutually_exclusive=['foo'], fields={}) + VersionedAPIData(mutually_exclusive=['foo'], fields={}) assert exc.value.args[0] == 'Mutually exclusive element at index #1 must be a list!' with pytest.raises(ValueError) as exc: - APIData(mutually_exclusive=[['foo']], fields={}) + VersionedAPIData(mutually_exclusive=[['foo']], fields={}) assert exc.value.args[0] == 'Mutually exclusive key foo must be in fields!' diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index a5ddb31..c7e32b8 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -9,6 +9,9 @@ __metaclass__ = type from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS +FAKE_ROS_VERSION = '7.0.0' + + class FakeLibRouterosError(Exception): def __init__(self, message): self.message = message @@ -16,7 +19,7 @@ class FakeLibRouterosError(Exception): class TrapError(FakeLibRouterosError): - def __init__(self, message="failure: already have interface with such name"): + def __init__(self, message='failure: already have interface with such name'): super(TrapError, self).__init__(message) @@ -133,7 +136,9 @@ def _normalize_entry(entry, path_info, on_create=False): def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=False, remove_builtin=False): - path_info = PATHS[path] + versioned_path_info = PATHS[path] + versioned_path_info.provide_version(FAKE_ROS_VERSION) + path_info = versioned_path_info.get_data() if remove_dynamic: values = [entry for entry in values if not entry.get('dynamic', False)] if remove_builtin: @@ -155,7 +160,9 @@ def massage_expected_result_data(values, path, keep_all=False, remove_dynamic=Fa class Path(object): def __init__(self, path, initial_values, read_only=False): self._path = path - self._path_info = PATHS[path] + versioned_path_info = PATHS[path] + versioned_path_info.provide_version(FAKE_ROS_VERSION) + self._path_info = versioned_path_info.get_data() self._values = [entry.copy() for entry in initial_values] for entry in self._values: _normalize_entry(entry, self._path_info) diff --git a/update-docs.py b/update-docs.py index 17a431b..05a9ee7 100755 --- a/update-docs.py +++ b/update-docs.py @@ -9,7 +9,12 @@ Updates DOCUMENTATION of modules using module_utils._api_data with the correct list of supported paths. ''' -from plugins.module_utils._api_data import ( +import sys + +# Ensure that we can import things from ansible_collections +sys.path.append('../../..') + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( PATHS, join_path, ) From dcc1cf441d35b1b81944cf0bcb7add40eda46236 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 1 Sep 2023 23:17:47 +0200 Subject: [PATCH 161/365] Allow to differ on API paths based on RouterOS version (2/2) (#212) * Allow to add versioned field for paths. * The field added in 1aa41ad3755909ca5f212934d582fa27fb1c66be is RouterOS 7.7+. * The fields added in 2e1159b4c401525e5882681c1ff96761ea1f8d69 are RouterOS 7.5+. --- plugins/module_utils/_api_data.py | 78 +++++++++++++++---- tests/unit/plugins/modules/fake_api.py | 2 +- tests/unit/plugins/modules/test_api_info.py | 9 ++- tests/unit/plugins/modules/test_api_modify.py | 7 +- 4 files changed, 79 insertions(+), 17 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 867e51e..d85f496 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -37,7 +37,7 @@ class APIData(object): self.unversioned = unversioned self.versioned = versioned if self.unversioned is not None: - self.needs_version = False + self.needs_version = self.unversioned.needs_version self.fully_understood = self.unversioned.fully_understood else: self.needs_version = self.versioned is not None @@ -47,30 +47,35 @@ class APIData(object): if unversioned.fully_understood: self.fully_understood = True break + self._current = None if self.needs_version else self.unversioned def provide_version(self, version): if not self.needs_version: return self.unversioned.fully_understood api_version = LooseVersion(version) - for other_version, comparator, unversioned in self.versioned: + if self.unversioned is not None: + self._current = self.unversioned.specialize_for_version(api_version) + return self._current.fully_understood + for other_version, comparator, data in self.versioned: if other_version == '*' and comparator == '*': - self.unversioned = unversioned - return self.unversioned.fully_supported + self._current = data.specialize_for_version(api_version) + return self._current.fully_supported other_api_version = LooseVersion(other_version) if _compare(api_version, other_api_version, comparator): - self.unversioned = unversioned - return self.unversioned.fully_supported - self.unversioned = None + self._current = data.specialize_for_version(api_version) + return self._current.fully_supported + self._current = None return False def get_data(self): - if self.unversioned is None: + if self._current is None: raise ValueError('either provide_version() was not called or it returned False') - return self.unversioned + return self._current class VersionedAPIData(object): - def __init__(self, primary_keys=None, + def __init__(self, + primary_keys=None, stratify_keys=None, required_one_of=None, mutually_exclusive=None, @@ -79,7 +84,8 @@ class VersionedAPIData(object): unknown_mechanism=False, fully_understood=False, fixed_entries=False, - fields=None): + fields=None, + versioned_fields=None): if sum([primary_keys is not None, stratify_keys is not None, has_identifier, single_value, unknown_mechanism]) > 1: raise ValueError('primary_keys, stratify_keys, has_identifier, single_value, and unknown_mechanism are mutually exclusive') if unknown_mechanism and fully_understood: @@ -98,6 +104,17 @@ class VersionedAPIData(object): if fields is None: raise ValueError('fields must be provided') self.fields = fields + if versioned_fields is not None: + if not isinstance(versioned_fields, list): + raise ValueError('unversioned_fields must be a list') + for conditions, name, field in versioned_fields: + if not isinstance(conditions, (tuple, list)): + raise ValueError('conditions must be a list or tuple') + if not isinstance(field, KeyInfo): + raise ValueError('field must be a KeyInfo object') + if name in fields: + raise ValueError('"{name}" appears both in fields and versioned_fields'.format(name=name)) + self.versioned_fields = versioned_fields or [] if primary_keys: for pk in primary_keys: if pk not in fields: @@ -120,6 +137,35 @@ class VersionedAPIData(object): for ek in exclusive_list: if ek not in fields: raise ValueError('Mutually exclusive key {ek} must be in fields!'.format(ek=ek)) + self.needs_version = len(self.versioned_fields) > 0 + + def specialize_for_version(self, api_version): + fields = self.fields.copy() + for conditions, name, field in self.versioned_fields: + matching = True + for other_version, comparator in conditions: + other_api_version = LooseVersion(other_version) + if not _compare(api_version, other_api_version, comparator): + matching = False + break + if matching: + if name in fields: + raise ValueError( + 'Internal error: field "{field}" already exists for {version}'.format(field=name, version=api_version) + ) + fields[name] = field + return VersionedAPIData( + primary_keys=self.primary_keys, + stratify_keys=self.stratify_keys, + required_one_of=self.required_one_of, + mutually_exclusive=self.mutually_exclusive, + has_identifier=self.has_identifier, + single_value=self.single_value, + unknown_mechanism=self.unknown_mechanism, + fully_understood=self.fully_understood, + fixed_entries=self.fixed_entries, + fields=fields, + ) class KeyInfo(object): @@ -1241,10 +1287,12 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.7', '>=')], 'mode', KeyInfo(default='tx-and-rx')), + ], fields={ 'discover-interface-list': KeyInfo(), 'lldp-med-net-policy-vlan': KeyInfo(default='disabled'), - 'mode': KeyInfo(default='tx-and-rx'), 'protocol': KeyInfo(default='cdp,lldp,mndp'), }, ), @@ -1797,14 +1845,16 @@ PATHS = { fully_understood=True, required_one_of=[['name', 'regexp']], mutually_exclusive=[['name', 'regexp']], + versioned_fields=[ + ([('7.5', '>=')], 'address-list', KeyInfo()), + ([('7.5', '>=')], 'match-subdomain', KeyInfo(default=False)), + ], fields={ 'address': KeyInfo(), - 'address-list': KeyInfo(), 'cname': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'forward-to': KeyInfo(), - 'match-subdomain': KeyInfo(default=False), 'mx-exchange': KeyInfo(), 'mx-preference': KeyInfo(), 'name': KeyInfo(), diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index c7e32b8..c934bc9 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -9,7 +9,7 @@ __metaclass__ = type from ansible_collections.community.routeros.plugins.module_utils._api_data import PATHS -FAKE_ROS_VERSION = '7.0.0' +FAKE_ROS_VERSION = '7.5.0' class FakeLibRouterosError(Exception): diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 2dabc36..cd83d8a 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -7,7 +7,9 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock -from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api +from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( + FAKE_ROS_VERSION, FakeLibRouterosError, Key, fake_ros_api, +) from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_info @@ -22,6 +24,10 @@ class TestRouterosApiInfoModule(ModuleTestCase): self.module.check_has_library = MagicMock() self.patch_create_api = patch('ansible_collections.community.routeros.plugins.modules.api_info.create_api', MagicMock(new=fake_ros_api)) self.patch_create_api.start() + self.patch_get_api_version = patch( + 'ansible_collections.community.routeros.plugins.modules.api_info.get_api_version', + MagicMock(return_value=FAKE_ROS_VERSION)) + self.patch_get_api_version.start() self.module.Key = MagicMock(new=Key) self.config_module_args = { 'username': 'admin', @@ -30,6 +36,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): } def tearDown(self): + self.patch_get_api_version.stop() self.patch_create_api.stop() def test_module_fail_when_required_args_missing(self): diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index ed9bfce..f4aa777 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -8,7 +8,7 @@ __metaclass__ = type from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( - FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, + FAKE_ROS_VERSION, FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, ) from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_modify @@ -302,6 +302,10 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'ansible_collections.community.routeros.plugins.modules.api_modify.create_api', MagicMock(new=fake_ros_api)) self.patch_create_api.start() + self.patch_get_api_version = patch( + 'ansible_collections.community.routeros.plugins.modules.api_modify.get_api_version', + MagicMock(return_value=FAKE_ROS_VERSION)) + self.patch_get_api_version.start() self.config_module_args = { 'username': 'admin', 'password': 'pаss', @@ -309,6 +313,7 @@ class TestRouterosApiModifyModule(ModuleTestCase): } def tearDown(self): + self.patch_get_api_version.stop() self.patch_create_api.stop() def test_module_fail_when_required_args_missing(self): From 23509130757a96b6d8a729e35e2439579a8b4c1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:27:04 +0200 Subject: [PATCH 162/365] Bump actions/checkout from 3 to 4 (#214) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ee.yml | 2 +- .github/workflows/extra-tests.yml | 2 +- .github/workflows/import-galaxy.yml | 2 +- .github/workflows/reuse.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index ae9a3db..82e2843 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -81,7 +81,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 952ebd3..92169fd 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index d38b157..5825597 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./checkout diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index acd7bc8..cd342bd 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | From 4d8ebaeb8d06699920a5181f15da188cd4d260f9 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 10 Sep 2023 21:46:14 +0200 Subject: [PATCH 163/365] Add support for "routing table" (#215) Signed-off-by: Michael Hanselmann --- changelogs/fragments/215-add-routing-table.yml | 2 ++ plugins/module_utils/_api_data.py | 13 +++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 17 insertions(+) create mode 100644 changelogs/fragments/215-add-routing-table.yml diff --git a/changelogs/fragments/215-add-routing-table.yml b/changelogs/fragments/215-add-routing-table.yml new file mode 100644 index 0000000..0f42a13 --- /dev/null +++ b/changelogs/fragments/215-add-routing-table.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing table`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/215). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d85f496..6a154f5 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -939,6 +939,19 @@ PATHS = { }, ), ), + ('routing', 'table'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'name': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'fib': KeyInfo(), + }, + )), + ], + ), ('snmp', 'community'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 787acfc..c616ff4 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -163,6 +163,7 @@ options: - routing pimsm interface-template - routing rip - routing ripng + - routing table - snmp - snmp community - system clock diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 308b98c..447be9a 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -168,6 +168,7 @@ options: - routing pimsm interface-template - routing rip - routing ripng + - routing table - snmp - snmp community - system clock From cf6c79e1b3868ce585d5d557bfd592c4f0488669 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 17 Sep 2023 14:34:09 +0200 Subject: [PATCH 164/365] Implement basic support for read-only and write-only keys in api_info and api_modify (#213) * Implement basic support for read-only and write-only keys in api_info and api_modify. * Do not show write-only fields as 'disabled'. --- changelogs/fragments/213-read-write-only.yml | 3 + plugins/module_utils/_api_data.py | 15 +++- plugins/modules/api_info.py | 16 +++- plugins/modules/api_modify.py | 73 +++++++++++++++++++ .../plugins/module_utils/test__api_data.py | 4 + tests/unit/plugins/modules/fake_api.py | 30 +++++++- 6 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/213-read-write-only.yml diff --git a/changelogs/fragments/213-read-write-only.yml b/changelogs/fragments/213-read-write-only.yml new file mode 100644 index 0000000..3b8bb53 --- /dev/null +++ b/changelogs/fragments/213-read-write-only.yml @@ -0,0 +1,3 @@ +minor_changes: + - "api_info - add new ``include_read_only`` option to select behavior for read-only values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213)." + - "api_modify - add new ``handle_read_only`` and ``handle_write_only`` options to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 6a154f5..af1f3c0 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -169,7 +169,16 @@ class VersionedAPIData(object): class KeyInfo(object): - def __init__(self, _dummy=None, can_disable=False, remove_value=None, absent_value=None, default=None, required=False, automatically_computed_from=None): + def __init__(self, + _dummy=None, + can_disable=False, + remove_value=None, + absent_value=None, + default=None, + required=False, + automatically_computed_from=None, + read_only=False, + write_only=False): if _dummy is not None: raise ValueError('KeyInfo() does not have positional arguments') if sum([required, default is not None or can_disable, automatically_computed_from is not None]) > 1: @@ -180,12 +189,16 @@ class KeyInfo(object): raise ValueError('remove_value can only be specified if can_disable=True') if absent_value is not None and any([default is not None, automatically_computed_from is not None, can_disable]): raise ValueError('absent_value can not be combined with default, automatically_computed_from, can_disable=True, or absent_value') + if read_only and write_only: + raise ValueError('read_only and write_only cannot be used at the same time') self.can_disable = can_disable self.remove_value = remove_value self.automatically_computed_from = automatically_computed_from self.default = default self.required = required self.absent_value = absent_value + self.read_only = read_only + self.write_only = write_only def split_path(path): diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index c616ff4..340627a 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -235,6 +235,13 @@ options: type: bool default: false version_added: 2.4.0 + include_read_only: + description: + - Whether to include read-only fields. + - By default, they are not returned. + type: bool + default: false + version_added: 2.10.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -314,6 +321,7 @@ def main(): hide_defaults=dict(type='bool', default=True), include_dynamic=dict(type='bool', default=False), include_builtin=dict(type='bool', default=False), + include_read_only=dict(type='bool', default=False), ) module_args.update(api_argument_spec()) @@ -339,6 +347,7 @@ def main(): hide_defaults = module.params['hide_defaults'] include_dynamic = module.params['include_dynamic'] include_builtin = module.params['include_builtin'] + include_read_only = module.params['include_read_only'] try: api_path = compose_api_path(api, path) @@ -362,7 +371,10 @@ def main(): if k not in path_info.fields: entry.pop(k) if handle_disabled != 'omit': - for k in path_info.fields: + for k, field_info in path_info.fields.items(): + if field_info.write_only: + entry.pop(k, None) + continue if k not in entry: if handle_disabled == 'exclamation': k = '!%s' % k @@ -373,6 +385,8 @@ def main(): entry.pop(k) if field_info.absent_value and k not in entry: entry[k] = field_info.absent_value + if not include_read_only and k in entry and field_info.read_only: + entry.pop(k) result.append(entry) module.exit_json(result=result) diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 447be9a..0b4cbdc 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -24,6 +24,10 @@ description: - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). +notes: + - If write-only fields are present in the path, the module is B(not idempotent) in a strict sense, + since it is not able to verify the current value of these fields. The behavior the module should + assume can be controlled with the O(handle_write_only) option. requirements: - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6 extends_documentation_fragment: @@ -234,12 +238,42 @@ options: - If V(remove), they are removed. If at least one cannot be removed, the module will fail. - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that cannot be removed will be kept. + - Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields. type: str choices: - ignore - remove - remove_as_much_as_possible default: ignore + handle_read_only: + description: + - How to handle values passed in for read-only fields. + - If V(ignore), they are not passed to the API. + - If V(validate), the values are not passed for creation, and for updating they are compared to the value returned for the object. + If they differ, the module fails. + - If V(error), the module will fail if read-only fields are provided. + type: str + choices: + - ignore + - validate + - error + default: error + version_added: 2.10.0 + handle_write_only: + description: + - How to handle values passed in for write-only fields. + - If V(create_only), they are passed on creation, and ignored for updating. + - If V(always_update), they are always passed to the API. This means that if such a value is present, + the module will always result in C(changed) since there is no way to validate whether the value + actually changed. + - If V(error), the module will fail if write-only fields are provided. + type: str + choices: + - create_only + - always_update + - error + default: create_only + version_added: 2.10.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -386,6 +420,18 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret continue if k not in old_entry and path_info.fields[k].default == v and not path_info.fields[k].can_disable: continue + key_info = path_info.fields[k] + if key_info.read_only: + # handle_read_only must be 'validate' + if old_entry.get(k) != v: + module.fail_json( + msg='Read-only key "{key}" has value "{old_value}", but should have new value "{new_value}"{for_text}.'.format( + key=k, old_value=old_entry.get(k), new_value=v, for_text=for_text)) + continue + if key_info.write_only: + if module.params['handle_write_only'] == 'create_only': + # do not update this value + continue if k not in old_entry or old_entry[k] != v: modifications[k] = v updated_entry[k] = v @@ -454,6 +500,18 @@ def essentially_same_weight(old_entry, new_entry, path_info, module): return weight +def remove_read_only(entry, path_info): + to_remove = [] + for real_k, v in entry.items(): + k = real_k + if k.startswith('!'): + k = k[1:] + if path_info.fields[k].read_only: + to_remove.append(real_k) + for k in to_remove: + entry.pop(k) + + def format_pk(primary_keys, values): return ', '.join('{pk}="{value}"'.format(pk=pk, value=value) for pk, value in zip(primary_keys, values)) @@ -461,6 +519,7 @@ def format_pk(primary_keys, values): def polish_entry(entry, path_info, module, for_text): if '.id' in entry: entry.pop('.id') + to_remove = [] for key, value in entry.items(): real_key = key disabled_key = False @@ -480,6 +539,16 @@ def polish_entry(entry, path_info, module, for_text): elif value is None: if not key_info.can_disable: module.fail_json(msg='Key "{key}" must not be disabled (value null/~/None){for_text}.'.format(key=key, for_text=for_text)) + if key_info.read_only: + if module.params['handle_read_only'] == 'error': + module.fail_json(msg='Key "{key}" is read-only{for_text}, and handle_read_only=error.'.format(key=key, for_text=for_text)) + if module.params['handle_read_only'] == 'ignore': + to_remove.append(real_key) + if key_info.write_only: + if module.params['handle_write_only'] == 'error': + module.fail_json(msg='Key "{key}" is write-only{for_text}, and handle_write_only=error.'.format(key=key, for_text=for_text)) + for key in to_remove: + entry.pop(key) for key, field_info in path_info.fields.items(): if field_info.required and key not in entry: module.fail_json(msg='Key "{key}" must be present{for_text}.'.format(key=key, for_text=for_text)) @@ -635,6 +704,7 @@ def sync_list(module, api, path, path_info): new_data.append((old_index, updated_entry)) new_entry['.id'] = old_entry['.id'] else: + remove_read_only(new_entry, path_info) create_list.append(new_entry) if handle_absent_entries == 'remove': @@ -827,6 +897,7 @@ def sync_with_primary_keys(module, api, path, path_info): for primary_key in primary_keys ]), )) + remove_read_only(new_entry, path_info) create_list.append(new_entry) new_entry = new_entry.copy() for key in list(new_entry): @@ -1028,6 +1099,8 @@ def main(): handle_absent_entries=dict(type='str', choices=['ignore', 'remove'], default='ignore'), handle_entries_content=dict(type='str', choices=['ignore', 'remove', 'remove_as_much_as_possible'], default='ignore'), ensure_order=dict(type='bool', default=False), + handle_read_only=dict(type='str', default='error', choices=['ignore', 'validate', 'error']), + handle_write_only=dict(type='str', default='create_only', choices=['create_only', 'always_update', 'error']), ) module_args.update(api_argument_spec()) diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 2dfe8cd..28f4161 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -99,6 +99,10 @@ def test_key_info_errors(): KeyInfo(remove_value='') assert exc.value.args[0] == 'remove_value can only be specified if can_disable=True' + with pytest.raises(ValueError) as exc: + KeyInfo(read_only=True, write_only=True) + assert exc.value.args[0] == 'read_only and write_only cannot be used at the same time' + SPLITTED_PATHS = [ ('', [], ''), diff --git a/tests/unit/plugins/modules/fake_api.py b/tests/unit/plugins/modules/fake_api.py index c934bc9..cbcd237 100644 --- a/tests/unit/plugins/modules/fake_api.py +++ b/tests/unit/plugins/modules/fake_api.py @@ -169,8 +169,16 @@ class Path(object): self._new_id_counter = 0 self._read_only = read_only + def _sanitize(self, entry): + entry = entry.copy() + for field, field_info in self._path_info.fields.items(): + if field in entry: + if field_info.write_only: + del entry[field] + return entry + def __iter__(self): - return [entry.copy() for entry in self._values].__iter__() + return [self._sanitize(entry) for entry in self._values].__iter__() def _find_id(self, id, required=False): for index, entry in enumerate(self._values): @@ -194,7 +202,15 @@ class Path(object): entry = { '.id': id, } - entry.update(kwargs) + for field, value in kwargs.items(): + if field.startswith('!'): + field = field[1:] + if field not in self._path_info.fields: + raise ValueError('Trying to set unknown field "{field}"'.format(field=field)) + field_info = self._path_info.fields[field] + if field_info.read_only: + raise ValueError('Trying to set read-only field "{field}"'.format(field=field)) + entry[field] = value _normalize_entry(entry, self._path_info, on_create=True) self._values.append(entry) return id @@ -223,6 +239,16 @@ class Path(object): entry = self._values[index] if entry.get('dynamic', False) or entry.get('builtin', False): raise Exception('Trying to update a dynamic or builtin entry') + for field in kwargs: + if field == '.id': + continue + if field.startswith('!'): + field = field[1:] + if field not in self._path_info.fields: + raise ValueError('Trying to update unknown field "{field}"'.format(field=field)) + field_info = self._path_info.fields[field] + if field_info.read_only: + raise ValueError('Trying to update read-only field "{field}"'.format(field=field)) entry.update(kwargs) _normalize_entry(entry, self._path_info) From 2bbaf26484daffa0e06391fc8c265d7a9a785b1f Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 17 Sep 2023 14:37:29 +0200 Subject: [PATCH 165/365] Finalize fields for "ppp profile" (#217) A few defaults were missing for `ppp profile`. Mark the path as fully understood to enable its use in Ansible tasks. Signed-off-by: Michael Hanselmann --- changelogs/fragments/217-ppp-profiles.yml | 2 ++ plugins/module_utils/_api_data.py | 27 ++++++++++++----------- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 changelogs/fragments/217-ppp-profiles.yml diff --git a/changelogs/fragments/217-ppp-profiles.yml b/changelogs/fragments/217-ppp-profiles.yml new file mode 100644 index 0000000..4412e2c --- /dev/null +++ b/changelogs/fragments/217-ppp-profiles.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - finalize fields for the ``ppp profile`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/217). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index af1f3c0..0939675 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3339,36 +3339,37 @@ PATHS = { ), ('ppp', 'profile'): APIData( unversioned=VersionedAPIData( - has_identifier=True, + fully_understood=True, + primary_keys=('name', ), fields={ - 'address-list': KeyInfo(), + 'address-list': KeyInfo(default=''), 'bridge': KeyInfo(can_disable=True), 'bridge-horizon': KeyInfo(can_disable=True), - 'bridge-learning': KeyInfo(), + 'bridge-learning': KeyInfo(default='default'), 'bridge-path-cost': KeyInfo(can_disable=True), 'bridge-port-priority': KeyInfo(can_disable=True), - 'change-tcp-mss': KeyInfo(), + 'change-tcp-mss': KeyInfo(default=True), 'dns-server': KeyInfo(can_disable=True), 'idle-timeout': KeyInfo(can_disable=True), 'incoming-filter': KeyInfo(can_disable=True), 'insert-queue-before': KeyInfo(can_disable=True), 'interface-list': KeyInfo(can_disable=True), 'local-address': KeyInfo(can_disable=True), - 'name': KeyInfo(), - 'on-down': KeyInfo(), - 'on-up': KeyInfo(), - 'only-one': KeyInfo(), + 'name': KeyInfo(required=True), + 'on-down': KeyInfo(default=''), + 'on-up': KeyInfo(default=''), + 'only-one': KeyInfo(default='default'), 'outgoing-filter': KeyInfo(can_disable=True), 'parent-queue': KeyInfo(can_disable=True), 'queue-type': KeyInfo(can_disable=True), 'rate-limit': KeyInfo(can_disable=True), 'remote-address': KeyInfo(can_disable=True), 'session-timeout': KeyInfo(can_disable=True), - 'use-compression': KeyInfo(), - 'use-encryption': KeyInfo(), - 'use-ipv6': KeyInfo(), - 'use-mpls': KeyInfo(), - 'use-upnp': KeyInfo(), + 'use-compression': KeyInfo(default='default'), + 'use-encryption': KeyInfo(default='default'), + 'use-ipv6': KeyInfo(default=True), + 'use-mpls': KeyInfo(default='default'), + 'use-upnp': KeyInfo(default='default'), 'wins-server': KeyInfo(can_disable=True), }, ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 340627a..ca8347f 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -148,6 +148,7 @@ options: - mpls ldp - port firmware - ppp aaa + - ppp profile - queue interface - queue tree - radius incoming diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 0b4cbdc..6d65c80 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -157,6 +157,7 @@ options: - mpls ldp - port firmware - ppp aaa + - ppp profile - queue interface - queue tree - radius incoming From d601e10e221020255df83b45435bc72616ba6986 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 17 Sep 2023 14:37:54 +0200 Subject: [PATCH 166/365] Add support for "tool netwatch" (#216) Upstream documentation: https://help.mikrotik.com/docs/display/ROS/Netwatch Signed-off-by: Michael Hanselmann --- .../fragments/216-add-tool-netwatch.yml | 2 + plugins/module_utils/_api_data.py | 38 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 42 insertions(+) create mode 100644 changelogs/fragments/216-add-tool-netwatch.yml diff --git a/changelogs/fragments/216-add-tool-netwatch.yml b/changelogs/fragments/216-add-tool-netwatch.yml new file mode 100644 index 0000000..6e4d45f --- /dev/null +++ b/changelogs/fragments/216-add-tool-netwatch.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/216). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0939675..e581bc4 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3168,6 +3168,44 @@ PATHS = { }, ), ), + ('tool', 'netwatch'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'certificate': KeyInfo(), + 'check-certificate': KeyInfo(), + 'comment': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'down-script': KeyInfo(), + 'host': KeyInfo(required=True), + 'http-codes': KeyInfo(), + 'interval': KeyInfo(), + 'name': KeyInfo(), + 'packet-count': KeyInfo(), + 'packet-interval': KeyInfo(), + 'packet-size': KeyInfo(), + 'port': KeyInfo(), + 'src-address': KeyInfo(), + 'start-delay': KeyInfo(), + 'startup-delay': KeyInfo(), + 'test-script': KeyInfo(), + 'thr-avg': KeyInfo(), + 'thr-http-time': KeyInfo(), + 'thr-jitter': KeyInfo(), + 'thr-loss-count': KeyInfo(), + 'thr-loss-percent': KeyInfo(), + 'thr-max': KeyInfo(), + 'thr-stdev': KeyInfo(), + 'thr-tcp-conn-time': KeyInfo(), + 'timeout': KeyInfo(), + 'type': KeyInfo(default='simple'), + 'up-script': KeyInfo(), + }, + )), + ], + ), ('tool', 'romon'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index ca8347f..eca87d2 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -190,6 +190,7 @@ options: - tool mac-server - tool mac-server mac-winbox - tool mac-server ping + - tool netwatch - tool romon - tool sms - tool sniffer diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 6d65c80..3910516 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -199,6 +199,7 @@ options: - tool mac-server - tool mac-server mac-winbox - tool mac-server ping + - tool netwatch - tool romon - tool sms - tool sniffer From 81c418649702a1b60c34446f4bac676ca22fb41c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 17 Sep 2023 14:53:06 +0200 Subject: [PATCH 167/365] Prepare 2.10.0 release. --- changelogs/fragments/2.10.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.10.0.yml diff --git a/changelogs/fragments/2.10.0.yml b/changelogs/fragments/2.10.0.yml new file mode 100644 index 0000000..56de6d9 --- /dev/null +++ b/changelogs/fragments/2.10.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. diff --git a/galaxy.yml b/galaxy.yml index 2dc6366..7825ce1 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.9.0 +version: 2.10.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From f6ed27c5885a66ef8ea25b26bc94c6a507e56dc6 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 18 Sep 2023 06:45:08 +0200 Subject: [PATCH 168/365] Fix for "'VersionedAPIData' object has no attribute 'fully_supported'" (#219) Commit 4b09951 added code looking for a non-existent `fully_supported` attribute. Signed-off-by: Michael Hanselmann --- plugins/module_utils/_api_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e581bc4..5edfdfc 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -59,11 +59,11 @@ class APIData(object): for other_version, comparator, data in self.versioned: if other_version == '*' and comparator == '*': self._current = data.specialize_for_version(api_version) - return self._current.fully_supported + return self._current.fully_understood other_api_version = LooseVersion(other_version) if _compare(api_version, other_api_version, comparator): self._current = data.specialize_for_version(api_version) - return self._current.fully_supported + return self._current.fully_understood self._current = None return False From d235437f8f66816e7e2ac5ed4c2c3a30d02aa27c Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 18 Sep 2023 06:48:13 +0200 Subject: [PATCH 169/365] Add support for the "user" path (#211) Make it possible to manage users via the `user` path. Signed-off-by: Michael Hanselmann --- changelogs/fragments/211-user.yml | 2 ++ plugins/module_utils/_api_data.py | 14 ++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 18 insertions(+) create mode 100644 changelogs/fragments/211-user.yml diff --git a/changelogs/fragments/211-user.yml b/changelogs/fragments/211-user.yml new file mode 100644 index 0000000..e6bc29b --- /dev/null +++ b/changelogs/fragments/211-user.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5edfdfc..f88af82 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3282,6 +3282,20 @@ PATHS = { }, ), ), + ('user',): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'group': KeyInfo(), + 'name': KeyInfo(), + 'password': KeyInfo(write_only=True), + }, + ), + ), ('user', 'aaa'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index eca87d2..048f434 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -195,6 +195,7 @@ options: - tool sms - tool sniffer - tool traffic-generator + - user - user aaa - user group - user settings diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 3910516..352f843 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -204,6 +204,7 @@ options: - tool sms - tool sniffer - tool traffic-generator + - user - user aaa - user group - user settings From 170240480c86a069b64a04a5f94599a4432df578 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 19 Sep 2023 17:51:13 +0200 Subject: [PATCH 170/365] Add ansible-core 2.16 to the matrix. (#222) --- .github/workflows/ansible-test.yml | 5 +++++ README.md | 2 +- tests/sanity/ignore-2.17.txt | 1 + tests/sanity/ignore-2.17.txt.license | 3 +++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/sanity/ignore-2.17.txt create mode 100644 tests/sanity/ignore-2.17.txt.license diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index e50b2f8..0444f59 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -33,6 +33,7 @@ jobs: - stable-2.13 - stable-2.14 - stable-2.15 + - stable-2.16 - devel # Ansible-test on various stable branches does not yet work well with cgroups v2. # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 @@ -77,6 +78,7 @@ jobs: - stable-2.13 - stable-2.14 - stable-2.15 + - stable-2.16 - devel steps: @@ -137,6 +139,9 @@ jobs: # 2.15 - ansible: stable-2.15 python: "3.9" + # 2.16 + - ansible: stable-2.16 + python: "3.10" steps: - name: >- diff --git a/README.md b/README.md index 7378c34..f7fcfa2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can find [documentation for the modules and plugins in this collection here] ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, and ansible-core 2.16 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt new file mode 100644 index 0000000..ce635c3 --- /dev/null +++ b/tests/sanity/ignore-2.17.txt @@ -0,0 +1 @@ +update-docs.py shebang diff --git a/tests/sanity/ignore-2.17.txt.license b/tests/sanity/ignore-2.17.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.17.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From dc110500db0824ef73995ca29164497760f6b78a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 19 Sep 2023 18:02:26 +0200 Subject: [PATCH 171/365] Fix snmp path's engine-id/engine-id-suffix for ROS 7.10+. (#218) --- changelogs/fragments/218-snmp-engine-id.yml | 2 ++ plugins/module_utils/_api_data.py | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/218-snmp-engine-id.yml diff --git a/changelogs/fragments/218-snmp-engine-id.yml b/changelogs/fragments/218-snmp-engine-id.yml new file mode 100644 index 0000000..f9f47b6 --- /dev/null +++ b/changelogs/fragments/218-snmp-engine-id.yml @@ -0,0 +1,2 @@ +bugfixes: + - "api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` is only available on RouterOS 7.10+, and that ``engine-id`` is read-only on RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, https://github.com/ansible-collections/community.routeros/pull/218)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index f88af82..32f2448 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2920,8 +2920,6 @@ PATHS = { fields={ 'contact': KeyInfo(default=''), 'enabled': KeyInfo(default=False), - 'engine-id': KeyInfo(default=''), - 'engine-id-suffix': KeyInfo(default=''), 'location': KeyInfo(default=''), 'src-address': KeyInfo(default='::'), 'trap-community': KeyInfo(default='public'), @@ -2930,6 +2928,11 @@ PATHS = { 'trap-version': KeyInfo(default=1), 'trap-interfaces': KeyInfo(default=''), }, + versioned_fields=[ + ([('7.10', '<')], 'engine-id', KeyInfo(default='')), + ([('7.10', '>=')], 'engine-id', KeyInfo(read_only=True)), + ([('7.10', '>=')], 'engine-id-suffix', KeyInfo(default='')), + ], ), ), ('system', 'clock'): APIData( From efbc05ef73169925c11244fa7ad8a122030f79c3 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 28 Sep 2023 21:13:47 +0200 Subject: [PATCH 172/365] Fix typo in changelog. (#225) --- CHANGELOG.rst | 2 +- changelogs/changelog.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4d784a1..418c732 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -196,7 +196,7 @@ Known Issues ------------ - api_modify - when limits for entries in ``queue tree`` are defined as human readable - for example ``25M`` -, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - for example ``25000000`` (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). -- api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). +- api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemented for ROS6 due to the significant changes between ROS6 and ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). v2.3.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 9e81f12..7ff4033 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -276,8 +276,8 @@ releases: in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). - api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not - fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 - (https://github.com/ansible-collections/community.routeros/pull/131). + fully implemented for ROS6 due to the significant changes between ROS6 and + ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). minor_changes: - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers (https://github.com/ansible-collections/community.routeros/pull/124). From 29a01ea2409a24212ebf61f617658f04ff6bfe85 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 7 Oct 2023 14:24:56 +0200 Subject: [PATCH 173/365] Add support for the "ip dhcp-server option" path (#223) Make it possible to manage IPv4 DHCP server options. Signed-off-by: Michael Hanselmann --- .../223-add-ip-dhcp-server-option.yml | 2 ++ plugins/module_utils/_api_data.py | 22 +++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 28 insertions(+) create mode 100644 changelogs/fragments/223-add-ip-dhcp-server-option.yml diff --git a/changelogs/fragments/223-add-ip-dhcp-server-option.yml b/changelogs/fragments/223-add-ip-dhcp-server-option.yml new file mode 100644 index 0000000..49979b7 --- /dev/null +++ b/changelogs/fragments/223-add-ip-dhcp-server-option.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ip dhcp-server option`` and ``ip dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 32f2448..d5ca137 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1847,6 +1847,28 @@ PATHS = { }, ), ), + ('ip', 'dhcp-server', 'option'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'code': KeyInfo(required=True), + 'name': KeyInfo(), + 'value': KeyInfo(default=''), + 'force': KeyInfo(), + }, + ), + ), + ('ip', 'dhcp-server', 'option', 'sets'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'name': KeyInfo(required=True), + 'options': KeyInfo(), + }, + ), + ), ('ip', 'dns'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 048f434..cb7da79 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -99,6 +99,8 @@ options: - ip dhcp-server config - ip dhcp-server lease - ip dhcp-server network + - ip dhcp-server option + - ip dhcp-server option sets - ip dns - ip dns static - ip firewall address-list diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 352f843..4209297 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -108,6 +108,8 @@ options: - ip dhcp-server config - ip dhcp-server lease - ip dhcp-server network + - ip dhcp-server option + - ip dhcp-server option sets - ip dns - ip dns static - ip firewall address-list From 9b4774c78d43a6acd9656fee4fcca32035a934d8 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 7 Oct 2023 14:25:11 +0200 Subject: [PATCH 174/365] Add support for the "port remote-access" path (#224) Signed-off-by: Michael Hanselmann --- .../fragments/224-add-port-remote-access.yml | 2 ++ plugins/module_utils/_api_data.py | 14 ++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 18 insertions(+) create mode 100644 changelogs/fragments/224-add-port-remote-access.yml diff --git a/changelogs/fragments/224-add-port-remote-access.yml b/changelogs/fragments/224-add-port-remote-access.yml new file mode 100644 index 0000000..797e54e --- /dev/null +++ b/changelogs/fragments/224-add-port-remote-access.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d5ca137..57c9d8c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2840,6 +2840,20 @@ PATHS = { }, ), ), + ('port', 'remote-access'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'allowed-addresses': KeyInfo(default='0.0.0.0/0'), + 'channel': KeyInfo(default=0), + 'disabled': KeyInfo(default=False), + 'log-file': KeyInfo(default=""), + 'port': KeyInfo(required=True), + 'protocol': KeyInfo(default='rfc2217'), + 'tcp-port': KeyInfo(default=0), + }, + ), + ), ('ppp', 'aaa'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index cb7da79..644a20c 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -149,6 +149,7 @@ options: - mpls - mpls ldp - port firmware + - port remote-access - ppp aaa - ppp profile - queue interface diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 4209297..0a056e9 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -158,6 +158,7 @@ options: - mpls - mpls ldp - port firmware + - port remote-access - ppp aaa - ppp profile - queue interface From 226649ac13eea5ef1f12eee3bb53a4f0f9f45adf Mon Sep 17 00:00:00 2001 From: Andrei Costescu Date: Sat, 7 Oct 2023 14:25:52 +0200 Subject: [PATCH 175/365] Add upnp interfaces, graphing interface and resource (#227) * Add ip upnp interfaces * Add tool graphing interface and resource * Update changelog --- .../fragments/227-add-upnp-graphing.yml | 2 + plugins/module_utils/_api_data.py | 39 +++++++++++++++++++ plugins/modules/api_info.py | 3 ++ plugins/modules/api_modify.py | 3 ++ 4 files changed, 47 insertions(+) create mode 100644 changelogs/fragments/227-add-upnp-graphing.yml diff --git a/changelogs/fragments/227-add-upnp-graphing.yml b/changelogs/fragments/227-add-upnp-graphing.yml new file mode 100644 index 0000000..ae2f69e --- /dev/null +++ b/changelogs/fragments/227-add-upnp-graphing.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 57c9d8c..565b3bc 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2415,6 +2415,18 @@ PATHS = { }, ), ), + ('ip', 'upnp', 'interfaces'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', 'type'), + fields={ + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'type': KeyInfo(), + 'forced-ip': KeyInfo(can_disable=True), + }, + ), + ), ('ipv6', 'dhcp-client'): APIData( unversioned=VersionedAPIData( fully_understood=True, @@ -3180,6 +3192,33 @@ PATHS = { }, ), ), + ('tool', 'graphing', 'interface'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'allow-address': KeyInfo(default='0.0.0.0/0'), + 'interface': KeyInfo(default='all'), + 'store-on-disk': KeyInfo(default=True), + }, + )), + ], + ), + ('tool', 'graphing', 'resource'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'allow-address': KeyInfo(default='0.0.0.0/0'), + 'store-on-disk': KeyInfo(default=True), + }, + )), + ], + ), ('tool', 'mac-server'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 644a20c..1700ec2 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -133,6 +133,7 @@ options: - ip traffic-flow ipfix - ip traffic-flow target - ip upnp + - ip upnp interfaces - ipv6 address - ipv6 dhcp-client - ipv6 dhcp-server @@ -190,6 +191,8 @@ options: - tool bandwidth-server - tool e-mail - tool graphing + - tool graphing interface + - tool graphing resource - tool mac-server - tool mac-server mac-winbox - tool mac-server ping diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 0a056e9..59b0c49 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -142,6 +142,7 @@ options: - ip traffic-flow ipfix - ip traffic-flow target - ip upnp + - ip upnp interfaces - ipv6 address - ipv6 dhcp-client - ipv6 dhcp-server @@ -199,6 +200,8 @@ options: - tool bandwidth-server - tool e-mail - tool graphing + - tool graphing interface + - tool graphing resource - tool mac-server - tool mac-server mac-winbox - tool mac-server ping From a6979c7f3d181f490bf78abab6056078ddfec8e9 Mon Sep 17 00:00:00 2001 From: Andrei Costescu Date: Sat, 7 Oct 2023 14:38:37 +0200 Subject: [PATCH 176/365] Support routing id and bgp connection (#220) * Support "/routing id" https://help.mikrotik.com/docs/pages/viewpage.action?pageId=59965506 * Support "/routing bgp connection" https://help.mikrotik.com/docs/display/ROS/BGP#BGP-ConnectionMenu * Add changelog fragment * Add period. --------- Co-authored-by: Felix Fontein --- .../220-routing-id-bgp-connection.yml | 2 ++ plugins/module_utils/_api_data.py | 34 +++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 40 insertions(+) create mode 100644 changelogs/fragments/220-routing-id-bgp-connection.yml diff --git a/changelogs/fragments/220-routing-id-bgp-connection.yml b/changelogs/fragments/220-routing-id-bgp-connection.yml new file mode 100644 index 0000000..72e24d8 --- /dev/null +++ b/changelogs/fragments/220-routing-id-bgp-connection.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` (https://github.com/ansible-collections/community.routeros/pull/220). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 565b3bc..a0fc6f1 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2888,6 +2888,18 @@ PATHS = { }, ), ), + ('routing', 'id'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'id': KeyInfo(), + 'name': KeyInfo(), + 'select-dynamic-id': KeyInfo(), + 'select-from-vrf': KeyInfo(), + }, + ), + ), ('routing', 'bfd', 'interface'): APIData( unversioned=VersionedAPIData( unknown_mechanism=True, @@ -3533,6 +3545,28 @@ PATHS = { }, ), ), + ('routing', 'bgp', 'connection'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'as': KeyInfo(), + 'name': KeyInfo(required=True), + 'connect': KeyInfo(default=True), + 'listen': KeyInfo(default=True), + 'local.address': KeyInfo(), + 'local.port': KeyInfo(), + 'local.role': KeyInfo(required=True), + 'local.ttl': KeyInfo(), + 'remote.address': KeyInfo(required=True), + 'remote.port': KeyInfo(), + 'remote.as': KeyInfo(), + 'remote.allowed-as': KeyInfo(), + 'remote.ttl': KeyInfo(), + 'tcp-md5-key': KeyInfo(), + 'templates': KeyInfo(), + }, + ), + ), ('routing', 'bgp', 'instance'): APIData( unversioned=VersionedAPIData( fixed_entries=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 1700ec2..5a66ace 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -156,9 +156,11 @@ options: - queue interface - queue tree - radius incoming + - routing bgp connection - routing bgp instance - routing filter rule - routing filter select-rule + - routing id - routing mme - routing ospf area - routing ospf area range diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 59b0c49..bb06315 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -165,9 +165,11 @@ options: - queue interface - queue tree - radius incoming + - routing bgp connection - routing bgp instance - routing filter rule - routing filter select-rule + - routing id - routing mme - routing ospf area - routing ospf area range From 6a68469209c4a01090ca0c3ae78c70cb764fb330 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 7 Oct 2023 14:38:54 +0200 Subject: [PATCH 177/365] Add some read-only values to the user path. (#228) --- plugins/module_utils/_api_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index a0fc6f1..e876ac8 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3380,7 +3380,9 @@ PATHS = { 'address': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), + 'expired': KeyInfo(read_only=True), 'group': KeyInfo(), + 'last-logged-in': KeyInfo(read_only=True), 'name': KeyInfo(), 'password': KeyInfo(write_only=True), }, From 46d77ccc5c02095a5c79d729362ec4a02e7a4e1b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 8 Oct 2023 12:15:04 +0200 Subject: [PATCH 178/365] Release 2.10.0. --- CHANGELOG.rst | 37 +++++++++++ changelogs/changelog.yaml | 65 +++++++++++++++++++ .../195-add-interface-wireless-data.yml | 2 - ...197-dns-static-addrlist-matchsubdomain.yml | 2 - changelogs/fragments/198-ip-nd-mode.yml | 2 - .../fragments/199-add-interface-pppclient.yml | 2 - changelogs/fragments/2.10.0.yml | 1 - .../fragments/200-add-routing-filter.yml | 2 - .../fragments/201-add-user-settings.yml | 2 - .../203-wireless-security-profiles.yml | 2 - .../fragments/204-add-ipv6-firewall-nat.yml | 2 - changelogs/fragments/205-add-iot-modbus.yml | 2 - .../fragments/210-date-time-gmt-offset.yml | 2 - changelogs/fragments/211-user.yml | 2 - changelogs/fragments/213-read-write-only.yml | 3 - .../fragments/215-add-routing-table.yml | 2 - .../fragments/216-add-tool-netwatch.yml | 2 - changelogs/fragments/217-ppp-profiles.yml | 2 - changelogs/fragments/218-snmp-engine-id.yml | 2 - .../220-routing-id-bgp-connection.yml | 2 - .../223-add-ip-dhcp-server-option.yml | 2 - .../fragments/224-add-port-remote-access.yml | 2 - .../fragments/227-add-upnp-graphing.yml | 2 - 23 files changed, 102 insertions(+), 42 deletions(-) delete mode 100644 changelogs/fragments/195-add-interface-wireless-data.yml delete mode 100644 changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml delete mode 100644 changelogs/fragments/198-ip-nd-mode.yml delete mode 100644 changelogs/fragments/199-add-interface-pppclient.yml delete mode 100644 changelogs/fragments/2.10.0.yml delete mode 100644 changelogs/fragments/200-add-routing-filter.yml delete mode 100644 changelogs/fragments/201-add-user-settings.yml delete mode 100644 changelogs/fragments/203-wireless-security-profiles.yml delete mode 100644 changelogs/fragments/204-add-ipv6-firewall-nat.yml delete mode 100644 changelogs/fragments/205-add-iot-modbus.yml delete mode 100644 changelogs/fragments/210-date-time-gmt-offset.yml delete mode 100644 changelogs/fragments/211-user.yml delete mode 100644 changelogs/fragments/213-read-write-only.yml delete mode 100644 changelogs/fragments/215-add-routing-table.yml delete mode 100644 changelogs/fragments/216-add-tool-netwatch.yml delete mode 100644 changelogs/fragments/217-ppp-profiles.yml delete mode 100644 changelogs/fragments/218-snmp-engine-id.yml delete mode 100644 changelogs/fragments/220-routing-id-bgp-connection.yml delete mode 100644 changelogs/fragments/223-add-ip-dhcp-server-option.yml delete mode 100644 changelogs/fragments/224-add-port-remote-access.yml delete mode 100644 changelogs/fragments/227-add-upnp-graphing.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 418c732..4b4eb0c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,43 @@ Community RouterOS Release Notes .. contents:: Topics +v2.10.0 +======= + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_info - add new ``include_read_only`` option to select behavior for read-only values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213). +- api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). +- api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). +- api_info, api_modify - add support for the ``interface ppp-client`` path (https://github.com/ansible-collections/community.routeros/pull/199). +- api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). +- api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). +- api_info, api_modify - add support for the ``ip dhcp-server option`` and ``ip dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). +- api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). +- api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). +- api_info, api_modify - add support for the ``mode`` property in ``ip neighbor discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). +- api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). +- api_info, api_modify - add support for the ``routing filter rule`` and ``routing filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). +- api_info, api_modify - add support for the ``routing table`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/215). +- api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/216). +- api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). +- api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). +- api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). +- api_info, api_modify - finalize fields for the ``ppp profile`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/217). +- api_modify - add new ``handle_read_only`` and ``handle_write_only`` options to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213). +- api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` (https://github.com/ansible-collections/community.routeros/pull/220). + +Bugfixes +-------- + +- api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` is only available on RouterOS 7.10+, and that ``engine-id`` is read-only on RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, https://github.com/ansible-collections/community.routeros/pull/218). + v2.9.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 7ff4033..e3f69a4 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -189,6 +189,71 @@ releases: name: api_find_and_modify namespace: '' release_date: '2022-05-25' + 2.10.0: + changes: + bugfixes: + - api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` + is only available on RouterOS 7.10+, and that ``engine-id`` is read-only on + RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, + https://github.com/ansible-collections/community.routeros/pull/218). + minor_changes: + - api_info - add new ``include_read_only`` option to select behavior for read-only + values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213). + - api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` + introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). + - api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` + under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). + - api_info, api_modify - add support for the ``interface ppp-client`` path (https://github.com/ansible-collections/community.routeros/pull/199). + - api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). + - api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). + - api_info, api_modify - add support for the ``ip dhcp-server option`` and ``ip + dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). + - api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool + graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). + - api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). + - api_info, api_modify - add support for the ``mode`` property in ``ip neighbor + discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). + - api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). + - api_info, api_modify - add support for the ``routing filter rule`` and ``routing + filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). + - api_info, api_modify - add support for the ``routing table`` path in RouterOS + 7 (https://github.com/ansible-collections/community.routeros/pull/215). + - api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS + 7 (https://github.com/ansible-collections/community.routeros/pull/216). + - api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). + - api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). + - api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` + path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). + - api_info, api_modify - finalize fields for the ``ppp profile`` path and enable + it (https://github.com/ansible-collections/community.routeros/pull/217). + - api_modify - add new ``handle_read_only`` and ``handle_write_only`` options + to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213). + - api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` + (https://github.com/ansible-collections/community.routeros/pull/220). + release_summary: Bugfix and feature release. + fragments: + - 195-add-interface-wireless-data.yml + - 197-dns-static-addrlist-matchsubdomain.yml + - 198-ip-nd-mode.yml + - 199-add-interface-pppclient.yml + - 2.10.0.yml + - 200-add-routing-filter.yml + - 201-add-user-settings.yml + - 203-wireless-security-profiles.yml + - 204-add-ipv6-firewall-nat.yml + - 205-add-iot-modbus.yml + - 210-date-time-gmt-offset.yml + - 211-user.yml + - 213-read-write-only.yml + - 215-add-routing-table.yml + - 216-add-tool-netwatch.yml + - 217-ppp-profiles.yml + - 218-snmp-engine-id.yml + - 220-routing-id-bgp-connection.yml + - 223-add-ip-dhcp-server-option.yml + - 224-add-port-remote-access.yml + - 227-add-upnp-graphing.yml + release_date: '2023-10-08' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/195-add-interface-wireless-data.yml b/changelogs/fragments/195-add-interface-wireless-data.yml deleted file mode 100644 index cdb91b5..0000000 --- a/changelogs/fragments/195-add-interface-wireless-data.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). diff --git a/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml b/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml deleted file mode 100644 index e683b4c..0000000 --- a/changelogs/fragments/197-dns-static-addrlist-matchsubdomain.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). diff --git a/changelogs/fragments/198-ip-nd-mode.yml b/changelogs/fragments/198-ip-nd-mode.yml deleted file mode 100644 index 5a892b2..0000000 --- a/changelogs/fragments/198-ip-nd-mode.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``mode`` property in ``ip neighbor discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). diff --git a/changelogs/fragments/199-add-interface-pppclient.yml b/changelogs/fragments/199-add-interface-pppclient.yml deleted file mode 100644 index 989ec9c..0000000 --- a/changelogs/fragments/199-add-interface-pppclient.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``interface ppp-client`` path (https://github.com/ansible-collections/community.routeros/pull/199). diff --git a/changelogs/fragments/2.10.0.yml b/changelogs/fragments/2.10.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/2.10.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. diff --git a/changelogs/fragments/200-add-routing-filter.yml b/changelogs/fragments/200-add-routing-filter.yml deleted file mode 100644 index 90594df..0000000 --- a/changelogs/fragments/200-add-routing-filter.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing filter rule`` and ``routing filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). diff --git a/changelogs/fragments/201-add-user-settings.yml b/changelogs/fragments/201-add-user-settings.yml deleted file mode 100644 index fdbc870..0000000 --- a/changelogs/fragments/201-add-user-settings.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). diff --git a/changelogs/fragments/203-wireless-security-profiles.yml b/changelogs/fragments/203-wireless-security-profiles.yml deleted file mode 100644 index 5eee689..0000000 --- a/changelogs/fragments/203-wireless-security-profiles.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). diff --git a/changelogs/fragments/204-add-ipv6-firewall-nat.yml b/changelogs/fragments/204-add-ipv6-firewall-nat.yml deleted file mode 100644 index b61ef39..0000000 --- a/changelogs/fragments/204-add-ipv6-firewall-nat.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). diff --git a/changelogs/fragments/205-add-iot-modbus.yml b/changelogs/fragments/205-add-iot-modbus.yml deleted file mode 100644 index 90a5875..0000000 --- a/changelogs/fragments/205-add-iot-modbus.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). diff --git a/changelogs/fragments/210-date-time-gmt-offset.yml b/changelogs/fragments/210-date-time-gmt-offset.yml deleted file mode 100644 index 7e3d114..0000000 --- a/changelogs/fragments/210-date-time-gmt-offset.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). diff --git a/changelogs/fragments/211-user.yml b/changelogs/fragments/211-user.yml deleted file mode 100644 index e6bc29b..0000000 --- a/changelogs/fragments/211-user.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). diff --git a/changelogs/fragments/213-read-write-only.yml b/changelogs/fragments/213-read-write-only.yml deleted file mode 100644 index 3b8bb53..0000000 --- a/changelogs/fragments/213-read-write-only.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - "api_info - add new ``include_read_only`` option to select behavior for read-only values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213)." - - "api_modify - add new ``handle_read_only`` and ``handle_write_only`` options to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213)." diff --git a/changelogs/fragments/215-add-routing-table.yml b/changelogs/fragments/215-add-routing-table.yml deleted file mode 100644 index 0f42a13..0000000 --- a/changelogs/fragments/215-add-routing-table.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing table`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/215). diff --git a/changelogs/fragments/216-add-tool-netwatch.yml b/changelogs/fragments/216-add-tool-netwatch.yml deleted file mode 100644 index 6e4d45f..0000000 --- a/changelogs/fragments/216-add-tool-netwatch.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/216). diff --git a/changelogs/fragments/217-ppp-profiles.yml b/changelogs/fragments/217-ppp-profiles.yml deleted file mode 100644 index 4412e2c..0000000 --- a/changelogs/fragments/217-ppp-profiles.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - finalize fields for the ``ppp profile`` path and enable it (https://github.com/ansible-collections/community.routeros/pull/217). diff --git a/changelogs/fragments/218-snmp-engine-id.yml b/changelogs/fragments/218-snmp-engine-id.yml deleted file mode 100644 index f9f47b6..0000000 --- a/changelogs/fragments/218-snmp-engine-id.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` is only available on RouterOS 7.10+, and that ``engine-id`` is read-only on RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, https://github.com/ansible-collections/community.routeros/pull/218)." diff --git a/changelogs/fragments/220-routing-id-bgp-connection.yml b/changelogs/fragments/220-routing-id-bgp-connection.yml deleted file mode 100644 index 72e24d8..0000000 --- a/changelogs/fragments/220-routing-id-bgp-connection.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` (https://github.com/ansible-collections/community.routeros/pull/220). diff --git a/changelogs/fragments/223-add-ip-dhcp-server-option.yml b/changelogs/fragments/223-add-ip-dhcp-server-option.yml deleted file mode 100644 index 49979b7..0000000 --- a/changelogs/fragments/223-add-ip-dhcp-server-option.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ip dhcp-server option`` and ``ip dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). diff --git a/changelogs/fragments/224-add-port-remote-access.yml b/changelogs/fragments/224-add-port-remote-access.yml deleted file mode 100644 index 797e54e..0000000 --- a/changelogs/fragments/224-add-port-remote-access.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). diff --git a/changelogs/fragments/227-add-upnp-graphing.yml b/changelogs/fragments/227-add-upnp-graphing.yml deleted file mode 100644 index ae2f69e..0000000 --- a/changelogs/fragments/227-add-upnp-graphing.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). From 8a4b37c90960cb229e9a7538a57bd2c40baac2ad Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 8 Oct 2023 12:45:40 +0200 Subject: [PATCH 179/365] Next expected release is 2.11.0. --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index 7825ce1..1a7be77 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.10.0 +version: 2.11.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From a823d66b33b309c970601f250120346c06536fdd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 29 Oct 2023 08:28:00 +0100 Subject: [PATCH 180/365] Fix typos, improve markup (#231) * Fix typos. * Improve markup. --- docs/docsite/rst/api-guide.rst | 10 +++++----- docs/docsite/rst/quoting.rst | 12 ++++++------ docs/docsite/rst/ssh-guide.rst | 14 +++++++------- plugins/modules/api.py | 2 +- tests/unit/plugins/module_utils/test__api_data.py | 10 +++++----- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index a672060..cb16fe8 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -8,7 +8,7 @@ How to connect to RouterOS devices with the RouterOS API ======================================================== -You can use the :ref:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. More specific module to modify certain entries are the :ref:`community.routeros.api_modify ` and :ref:`community.routeros.api_find_and_modify ` modules. The :ref:`community.routeros.api_info module ` allows to retrieve information on specific predefined paths that can be used as input for the ``community.routeros.api_modify`` module, and the :ref:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. +You can use the :ansplugin:`community.routeros.api module ` to connect to a RouterOS device with the RouterOS API. More specific module to modify certain entries are the :ansplugin:`community.routeros.api_modify ` and :ansplugin:`community.routeros.api_find_and_modify ` modules. The :ansplugin:`community.routeros.api_info module ` allows to retrieve information on specific predefined paths that can be used as input for the :ansplugin:`community.routeros.api_modify ` module, and the :ansplugin:`community.routeros.api_facts module ` allows to retrieve Ansible facts using the RouterOS API. No special setup is needed; the module needs to be run on a host that can connect to the device's API. The most common case is that the module is run on ``localhost``, either by using ``hosts: localhost`` in the playbook, or by using ``delegate_to: localhost`` for the task. The following example shows how to run the equivalent of ``/ip address print``: @@ -59,7 +59,7 @@ This results in the following output: PLAY RECAP ******************************************************************************************************* localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 -Check out the documenation of the :ref:`community.routeros.api module ` for details on the options. +Check out the documentation of the :ansplugin:`community.routeros.api module ` for details on the options. Using the ``community.routeros.api`` module defaults group ---------------------------------------------------------- @@ -110,7 +110,7 @@ It is recommended to always use :ansopt:`tls=true` when connecting with the API, :force_no_cert: Setting to :ansval:`true` connects to the device without a certificate. **This is discouraged to use in production and is susceptible to Man-in-the-Middle attacks**, but might be useful when setting the device up. The default value is :ansval:`false`. :validate_certs: Setting to :ansval:`false` disables any certificate validation. **This is discouraged to use in production**, but is needed when setting the device up. The default value is :ansval:`true`. :validate_cert_hostname: Setting to :ansval:`false` (default) disables hostname verification during certificate validation. This is needed if the hostnames specified in the certificate do not match the hostname used for connecting (usually the device's IP). It is recommended to set up the certificate correctly and set this to :ansval:`true`; the default :ansval:`false` is chosen for backwards compatibility to an older version of the module. -:ca_path: If you are not using a commerically trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate. +:ca_path: If you are not using a commercially trusted CA certificate to sign your device's certificate, or have not included your CA certificate in Python's truststore, you need to point this option to the CA certificate. We recommend to create a CA certificate that is used to sign the certificates for your RouterOS devices, and have the certificates include the correct hostname(s), including the IP of the device. That way, you can fully enable TLS and be sure that you always talk to the correct device. @@ -124,7 +124,7 @@ Installing a certificate on a MikroTik router Installing the certificate is best done with the SSH connection. (See the :ref:`ansible_collections.community.routeros.docsite.ssh-guide` guide for more information.) Once the certificate has been installed, and the HTTPS API enabled, it's easier to work with the API, since it has a quite a few less problems, and returns data as JSON objects instead of text you first have to parse. -First you have to convert the certificate and its private key to a `PKCS #12 bundle `_. This can be done with the :ref:`community.crypto.openssl_pkcs12 `. The following playbook assumes that the certificate is available as ``keys/{{ inventory_hostname }}.pem``, and its private key is available as ``keys/{{ inventory_hostname }}.key``. It generates a random passphrase to protect the PKCS#12 file. +First you have to convert the certificate and its private key to a `PKCS #12 bundle `_. This can be done with the :ansplugin:`community.crypto.openssl_pkcs12 `. The following playbook assumes that the certificate is available as ``keys/{{ inventory_hostname }}.pem``, and its private key is available as ``keys/{{ inventory_hostname }}.key``. It generates a random passphrase to protect the PKCS#12 file. .. code-block:: yaml+jinja @@ -186,7 +186,7 @@ First you have to convert the certificate and its private key to a `PKCS #12 bun The playbook also assumes that ``admin_network`` describes the network from which the HTTPS and API interface can be accessed. This can be for example ``192.168.1.0/24``. -When this playbook completed successfully, you should be able to use the HTTPS admin interface (reachable in a browser from ``https://192.168.1.1/``, with the correct IP inserted), as well as the :ref:`community.routeros.api module ` module with TLS and certificate validation enabled: +When this playbook completed successfully, you should be able to use the HTTPS admin interface (reachable in a browser from ``https://192.168.1.1/``, with the correct IP inserted), as well as the :ansplugin:`community.routeros.api module ` module with TLS and certificate validation enabled: .. code-block:: yaml+jinja diff --git a/docs/docsite/rst/quoting.rst b/docs/docsite/rst/quoting.rst index 1356f7b..b1c0453 100644 --- a/docs/docsite/rst/quoting.rst +++ b/docs/docsite/rst/quoting.rst @@ -8,12 +8,12 @@ How to quote and unquote commands and arguments =============================================== -When using the :ref:`community.routeros.command module ` or the :ref:`community.routeros.api module ` modules, you need to pass text data in quoted form. While in some cases quoting is not needed (when passing IP addresses or names without spaces, for example), in other cases it is required, like when passing a comment which contains a space. +When using the :ansplugin:`community.routeros.command module ` or the :ansplugin:`community.routeros.api module ` modules, you need to pass text data in quoted form. While in some cases quoting is not needed (when passing IP addresses or names without spaces, for example), in other cases it is required, like when passing a comment which contains a space. The community.routeros collection provides a set of Jinja2 filter plugins which helps you with these tasks: -- The :ref:`community.routeros.quote_argument_value filter ` quotes an argument value: ``'this is a "comment"' | community.routeros.quote_argument_value == '"this is a \\"comment\\""'``. -- The :ref:`community.routeros.quote_argument filter ` quotes an argument with or without a value: ``'comment=this is a "comment"' | community.routeros.quote_argument == 'comment="this is a \\"comment\\""'``. -- The :ref:`community.routeros.join filter ` quotes a list of arguments and joins them to one string: ``['foo=bar', 'comment=foo is bar'] | community.routeros.join == 'foo=bar comment="foo is bar"'``. -- The :ref:`community.routeros.split filter ` splits a command into a list of arguments (with or without values): ``'foo=bar comment="foo is bar"' | community.routeros.split == ['foo=bar', 'comment=foo is bar']`` -- The :ref:`community.routeros.list_to_dict filter ` splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: :ansopt:`community.routeros.list_to_dict#filter:require_assignment` (default value :ansval:`true`) allows to accept arguments without values when set to :ansval:`false`; and :ansopt:`community.routeros.list_to_dict#filter:skip_empty_values` (default value :ansval:`false`) allows to skip arguments whose value is empty. +- The :ansplugin:`community.routeros.quote_argument_value filter ` quotes an argument value: ``'this is a "comment"' | community.routeros.quote_argument_value == '"this is a \\"comment\\""'``. +- The :ansplugin:`community.routeros.quote_argument filter ` quotes an argument with or without a value: ``'comment=this is a "comment"' | community.routeros.quote_argument == 'comment="this is a \\"comment\\""'``. +- The :ansplugin:`community.routeros.join filter ` quotes a list of arguments and joins them to one string: ``['foo=bar', 'comment=foo is bar'] | community.routeros.join == 'foo=bar comment="foo is bar"'``. +- The :ansplugin:`community.routeros.split filter ` splits a command into a list of arguments (with or without values): ``'foo=bar comment="foo is bar"' | community.routeros.split == ['foo=bar', 'comment=foo is bar']`` +- The :ansplugin:`community.routeros.list_to_dict filter ` splits a list of arguments with values into a dictionary: ``['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict == {'foo': 'bar', 'comment': 'foo is bar'}``. It has two optional arguments: :ansopt:`community.routeros.list_to_dict#filter:require_assignment` (default value :ansval:`true`) allows to accept arguments without values when set to :ansval:`false`; and :ansopt:`community.routeros.list_to_dict#filter:skip_empty_values` (default value :ansval:`false`) allows to skip arguments whose value is empty. diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index 7d907c7..4b0eb20 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -10,17 +10,17 @@ How to connect to RouterOS devices with SSH The collection offers two modules to connect to RouterOS devies with SSH: -- The :ref:`community.routeros.facts module ` gathers facts about a RouterOS device; -- The :ref:`community.routeros.command module ` executes commands on a RouterOS device. +- The :ansplugin:`community.routeros.facts module ` gathers facts about a RouterOS device; +- The :ansplugin:`community.routeros.command module ` executes commands on a RouterOS device. -The modules need the :ref:`ansible.netcommon.network_cli connection plugin ` for this. +The modules need the :ansplugin:`ansible.netcommon.network_cli connection plugin ` for this. Important notes --------------- 1. The SSH-based modules do not support arbitrary symbols in the router's identity. If you are having trouble connecting to your device, please make sure that your MikroTik's identity contains only alphanumeric characters and dashes. Also make sure that the identity string is not longer than 19 characters (`see issue for details `__). Similar problems can happen for unsupported characters in your username. -2. The :ref:`community.routeros.command module ` does not support nesting commands and expects every command to start with a forward slash (``/``). Running the following command will produce an error: +2. The :ansplugin:`community.routeros.command module ` does not support nesting commands and expects every command to start with a forward slash (``/``). Running the following command will produce an error: .. code-block:: yaml+jinja @@ -29,9 +29,9 @@ Important notes - /ip - print -3. When using the :ref:`community.routeros.command module ` module, make sure to not specify too long commands. Alternatively, add something like ``+cet512w`` to the username (replace ``admin`` with ``admin+cet512w``) to tell RouterOS to not wrap before 512 characters in a line (`see issue for details `__). +3. When using the :ansplugin:`community.routeros.command module ` module, make sure to not specify too long commands. Alternatively, add something like ``+cet512w`` to the username (replace ``admin`` with ``admin+cet512w``) to tell RouterOS to not wrap before 512 characters in a line (`see issue for details `__). -4. The :ref:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. +4. The :ansplugin:`ansible.netcommon.network_cli connection plugin ` uses `paramiko `_ by default to connect to devices with SSH. You can set its :ansopt:`ansible.netcommon.network_cli#connection:ssh_type` option to :ansval:`libssh` to use `ansible-pylibssh `_ instead, which offers Python bindings to libssh. See its documentation for details. 5. User is **not allowed** to login via SSH by password to modern Mikrotik if SSH key for the user is added! @@ -51,7 +51,7 @@ An example inventory ``hosts`` file for a RouterOS device is as follows: ansible_user=admin ansible_ssh_pass=test1234 -This tells Ansible that you have a RouterOS device called ``router`` with IP ``192.168.2.1``. Ansible should use the :ref:`ansible.netcommon.network_cli connection plugin ` together with the the :ref:`community.routeros.routeros cliconf plugin `. The credentials are stored as ``ansible_user`` and ``ansible_ssh_pass`` in the inventory. +This tells Ansible that you have a RouterOS device called ``router`` with IP ``192.168.2.1``. Ansible should use the :ansplugin:`ansible.netcommon.network_cli connection plugin ` together with the the :ansplugin:`community.routeros.routeros cliconf plugin `. The credentials are stored as ``ansible_user`` and ``ansible_ssh_pass`` in the inventory. Connecting to the device ------------------------ diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 65b9796..4857a3c 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -224,7 +224,7 @@ EXAMPLES = ''' ansible.builtin.debug: msg: '{{ extended_queryout }}' -- name: Update example - ether2 ip addres with ".id = *14" +- name: Update example - ether2 ip address with ".id = *14" community.routeros.api: hostname: "{{ hostname }}" password: "{{ password }}" diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 28f4161..5a346eb 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -104,7 +104,7 @@ def test_key_info_errors(): assert exc.value.args[0] == 'read_only and write_only cannot be used at the same time' -SPLITTED_PATHS = [ +SPLIT_PATHS = [ ('', [], ''), (' ip ', ['ip'], 'ip'), ('ip', ['ip'], 'ip'), @@ -112,7 +112,7 @@ SPLITTED_PATHS = [ ] -@pytest.mark.parametrize("joined_input, splitted, joined_output", SPLITTED_PATHS) -def test_join_split_path(joined_input, splitted, joined_output): - assert split_path(joined_input) == splitted - assert join_path(splitted) == joined_output +@pytest.mark.parametrize("joined_input, split, joined_output", SPLIT_PATHS) +def test_join_split_path(joined_input, split, joined_output): + assert split_path(joined_input) == split + assert join_path(split) == joined_output From 1beddb585494cc6dd5c3cce646137af59b7a35a0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 7 Nov 2023 22:57:17 +0100 Subject: [PATCH 181/365] Fix CI. (#232) --- .github/workflows/extra-tests.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 92169fd..98a1e70 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -39,9 +39,12 @@ jobs: run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - name: Install collection dependencies - run: git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ./ansible_collections/community/internal_test_tools + run: | + git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ./ansible_collections/community/internal_test_tools + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ./ansible_collections/ansible/netcommon + git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ./ansible_collections/ansible/utils # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # run: ansible-galaxy collection install community.internal_test_tools -p . + # run: ansible-galaxy collection install community.internal_test_tools ansible.netcommon -p . - name: Run sanity tests run: ../../community/internal_test_tools/tools/run.py --color From 479f3106bf91fe77f3025e070a1b768cd12d9228 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 11 Nov 2023 23:10:10 +0100 Subject: [PATCH 182/365] Make wireless parameter "running" read-only (#233) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit e4a21311 added API data for the "interface wireless" path. It contained the read-only "running" parameter. Writing to the parameter fails: Error while modifying for name="…" (ID *3): unknown parameter running Signed-off-by: Michael Hanselmann --- changelogs/fragments/233-wireless-running-read-only.yml | 2 ++ plugins/module_utils/_api_data.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/233-wireless-running-read-only.yml diff --git a/changelogs/fragments/233-wireless-running-read-only.yml b/changelogs/fragments/233-wireless-running-read-only.yml new file mode 100644 index 0000000..a69aa58 --- /dev/null +++ b/changelogs/fragments/233-wireless-running-read-only.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - mark the ``interface wireless`` parameter ``running`` as read-only (https://github.com/ansible-collections/community.routeros/pull/233). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e876ac8..9f5afc2 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1563,7 +1563,7 @@ PATHS = { 'radio-name': KeyInfo(), 'rate-selection': KeyInfo(default='advanced'), 'rate-set': KeyInfo(default='default'), - 'running': KeyInfo(default=False), + 'running': KeyInfo(default=False, read_only=True), 'rx-chains': KeyInfo(default='0,1'), 'scan-list': KeyInfo(default='default'), 'secondary-frequency': KeyInfo(default=''), From 92c622639493c02d536f22c02cb8386080d91072 Mon Sep 17 00:00:00 2001 From: derdeagle Date: Sun, 19 Nov 2023 10:39:33 +0100 Subject: [PATCH 183/365] Fix some bugs and adapt RouterOS v.7.12 changes (#234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix some bugs and adapt RouterOS v.7.12 changes /ip traffic-flow target: make it a multiple value (single_value=False) field /routing id: add comment attribute /tool e-mail: add versioning to the parameters as "address" was renamed to "server" in 7.12 /routing bgp connection: add missing attributes * Add changelog fragment * Fix duplicate key 'output.network' * Split up the changelog fragment --------- Co-authored-by: Johannes Münch --- .../234-bugfixes-and-update-adaptations.yml | 5 ++ plugins/module_utils/_api_data.py | 86 +++++++++++++++---- 2 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 changelogs/fragments/234-bugfixes-and-update-adaptations.yml diff --git a/changelogs/fragments/234-bugfixes-and-update-adaptations.yml b/changelogs/fragments/234-bugfixes-and-update-adaptations.yml new file mode 100644 index 0000000..8105c1d --- /dev/null +++ b/changelogs/fragments/234-bugfixes-and-update-adaptations.yml @@ -0,0 +1,5 @@ +minor_changes: + - api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - make ``/ip traffic-flow target`` a multiple value attribute (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 release) (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add missing attributes to the ``routing bgp connection`` path (https://github.com/ansible-collections/community.routeros/pull/234). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9f5afc2..50ad1d0 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2390,7 +2390,7 @@ PATHS = { ), ('ip', 'traffic-flow', 'target'): APIData( unversioned=VersionedAPIData( - single_value=True, + single_value=False, fully_understood=True, fields={ 'address': KeyInfo(), @@ -2892,6 +2892,7 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'id': KeyInfo(), 'name': KeyInfo(), @@ -3180,19 +3181,36 @@ PATHS = { ), ), ('tool', 'e-mail'): APIData( - unversioned=VersionedAPIData( - single_value=True, - fully_understood=True, - fields={ - 'address': KeyInfo(default='0.0.0.0'), - 'from': KeyInfo(default='<>'), - 'password': KeyInfo(default=''), - 'port': KeyInfo(default=25), - 'start-tls': KeyInfo(default=False), - 'tls': KeyInfo(default=False), - 'user': KeyInfo(default=''), - }, - ), + versioned=[ + ('7.12', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'from': KeyInfo(default='<>'), + 'password': KeyInfo(default=''), + 'port': KeyInfo(default=25), + 'server': KeyInfo(default='0.0.0.0'), + 'start-tls': KeyInfo(default=False), + 'tls': KeyInfo(default=False), + 'user': KeyInfo(default=''), + 'vfr': KeyInfo(default=''), + }, + )), + ('7.12', '<', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'address': KeyInfo(default='0.0.0.0'), + 'from': KeyInfo(default='<>'), + 'password': KeyInfo(default=''), + 'port': KeyInfo(default=25), + 'start-tls': KeyInfo(default=False), + 'tls': KeyInfo(default=False), + 'user': KeyInfo(default=''), + 'vfr': KeyInfo(default=''), + }, + )), + ], ), ('tool', 'graphing'): APIData( unversioned=VersionedAPIData( @@ -3552,20 +3570,58 @@ PATHS = { fully_understood=True, fields={ 'as': KeyInfo(), - 'name': KeyInfo(required=True), + 'add-path-out': KeyInfo(), + 'address-families': KeyInfo(), + 'cisco-vpls-nlri-len-fmt': KeyInfo(), + 'cluster-id': KeyInfo(), + 'comment': KeyInfo(), 'connect': KeyInfo(default=True), + 'disabled': KeyInfo(), + 'hold-time': KeyInfo(), + 'input.accept-communities': KeyInfo(), + 'input.accept-ext-communities': KeyInfo(), + 'input.accept-large-communities': KeyInfo(), + 'input.accpet-nlri': KeyInfo(), + 'input.accept-unknown': KeyInfo(), + 'input.affinity': KeyInfo(), + 'input.allow-as': KeyInfo(), + 'input.filter': KeyInfo(), + 'input.ignore-as-path-len': KeyInfo(), + 'input.limit-process-routes-ipv4': KeyInfo(), + 'input.limit-process-routes-ipv6': KeyInfo(), + 'keepalive-time': KeyInfo(), 'listen': KeyInfo(default=True), 'local.address': KeyInfo(), 'local.port': KeyInfo(), 'local.role': KeyInfo(required=True), 'local.ttl': KeyInfo(), + 'multihop': KeyInfo(), + 'name': KeyInfo(required=True), + 'nexthop-choice': KeyInfo(), + 'output.affinity': KeyInfo(), + 'output.as-override': KeyInfo(), + 'output.default-originate': KeyInfo(), + 'output.default-prepend': KeyInfo(), + 'output.filter-chain': KeyInfo(), + 'output.filter-select': KeyInfo(), + 'output.keep-sent-attributes': KeyInfo(), + 'output.network': KeyInfo(), + 'output.no-client-to-client-reflection': KeyInfo(), + 'output.no-early-cut': KeyInfo(), + 'output.redistribute': KeyInfo(), + 'output.remote-private-as': KeyInfo(), 'remote.address': KeyInfo(required=True), 'remote.port': KeyInfo(), 'remote.as': KeyInfo(), 'remote.allowed-as': KeyInfo(), 'remote.ttl': KeyInfo(), + 'router-id': KeyInfo(), + 'routing-table': KeyInfo(), + 'save-to': KeyInfo(), 'tcp-md5-key': KeyInfo(), 'templates': KeyInfo(), + 'use-bfd': KeyInfo(), + 'vrf': KeyInfo(), }, ), ), From dac3b79a17e35d1e89b1429f73a83d446dc5fe74 Mon Sep 17 00:00:00 2001 From: derdeagle Date: Fri, 24 Nov 2023 21:07:40 +0100 Subject: [PATCH 184/365] Fixes #230: Add missing DoH parameters in the "ip dns" path (#235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - doh-max-concurrent-queries - doh-max-server-connections - doh-timeout The parameters mentioned above seem to be added in version 7.8 as far as I could tell from the changelogs. Co-authored-by: Johannes Münch --- changelogs/fragments/235-add-missing-dns-attributes.yml | 2 ++ plugins/module_utils/_api_data.py | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 changelogs/fragments/235-add-missing-dns-attributes.yml diff --git a/changelogs/fragments/235-add-missing-dns-attributes.yml b/changelogs/fragments/235-add-missing-dns-attributes.yml new file mode 100644 index 0000000..f2bf2f5 --- /dev/null +++ b/changelogs/fragments/235-add-missing-dns-attributes.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 50ad1d0..f786de8 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1873,6 +1873,11 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.8', '>=')], 'doh-max-concurrent-queries', KeyInfo(default=50)), + ([('7.8', '>=')], 'doh-max-server-connections', KeyInfo(default=5)), + ([('7.8', '>=')], 'doh-timeout', KeyInfo(default='5s')), + ], fields={ 'allow-remote-requests': KeyInfo(), 'cache-max-ttl': KeyInfo(default='1w'), From 7de154e907be71aa0e7dee0c636b0e15a751dc29 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 30 Nov 2023 06:41:36 +0100 Subject: [PATCH 185/365] Prepare 2.11.0 release. --- changelogs/fragments/2.11.0.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/fragments/2.11.0.yml diff --git a/changelogs/fragments/2.11.0.yml b/changelogs/fragments/2.11.0.yml new file mode 100644 index 0000000..80287c3 --- /dev/null +++ b/changelogs/fragments/2.11.0.yml @@ -0,0 +1 @@ +release_summary: Feature and bugfix release. From ad6faf275d71038863d24c46cbb54b02d57ff26f Mon Sep 17 00:00:00 2001 From: derdeagle Date: Sun, 3 Dec 2023 13:02:08 +0100 Subject: [PATCH 186/365] Fixes #236: Add missing parameters for the "ip firewall" subpaths and set the default value for the "disabled" parameter for most paths (#237) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #236: Add missing parameters The parameters "address-list", "address-list-timeout", and "realm" were missing for some subpaths of "ip firewall" and are now added. Additionally the default value of "False" for the "disabled" parameter has been set so that an e.g. firewall rule, which was disabled (disabled=True) is enabled (disabled=False) after removing the "disabled" argument in the data. Some more parameters can now be removed, e.g. "jump-target", "log", and "log-prefix", which are not mandatory. * Add missing changes for #236 Additionally fixed the PR id in the changelog fragment. * Update changelogs/fragments/237-add-missing-ip-firewall-attributes.yml Full stop added at the end of the changelog fragment Co-authored-by: Felix Fontein * Update changelogs/fragments/237-add-missing-ip-firewall-attributes.yml Full stop added at the end of the changelog fragment Co-authored-by: Felix Fontein * Fix unit tests --------- Co-authored-by: Johannes Münch Co-authored-by: Felix Fontein --- ...237-add-missing-ip-firewall-attributes.yml | 3 + plugins/module_utils/_api_data.py | 77 +++++++++++-------- .../modules/test_api_find_and_modify.py | 7 ++ tests/unit/plugins/modules/test_api_info.py | 6 ++ 4 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 changelogs/fragments/237-add-missing-ip-firewall-attributes.yml diff --git a/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml b/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml new file mode 100644 index 0000000..677fef5 --- /dev/null +++ b/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). + - api_info, api_modify - set the default value to ``false`` for the ``disabled`` parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index f786de8..747017a 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -959,7 +959,7 @@ PATHS = { fields={ 'name': KeyInfo(required=True), 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), 'fib': KeyInfo(), }, )), @@ -1007,7 +1007,7 @@ PATHS = { 'client-to-client-forwarding': KeyInfo(can_disable=True), 'client-tx-limit': KeyInfo(can_disable=True), 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'interface': KeyInfo(can_disable=True), 'mac-address': KeyInfo(can_disable=True), 'mac-address-mask': KeyInfo(can_disable=True), @@ -1941,6 +1941,8 @@ PATHS = { stratify_keys=('chain', ), fields={ 'action': KeyInfo(), + 'address-list': KeyInfo(can_disable=True), + 'address-list-timeout': KeyInfo(can_disable=True), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'connection-bytes': KeyInfo(can_disable=True), @@ -1951,7 +1953,7 @@ PATHS = { 'connection-state': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -1969,11 +1971,11 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), + 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), + 'log': KeyInfo(can_disable=True), + 'log-prefix': KeyInfo(can_disable=True), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -1988,7 +1990,8 @@ PATHS = { 'protocol': KeyInfo(can_disable=True), 'psd': KeyInfo(can_disable=True), 'random': KeyInfo(can_disable=True), - 'reject-with': KeyInfo(), + 'realm': KeyInfo(can_disable=True), + 'reject-with': KeyInfo(can_disable=True), 'routing-mark': KeyInfo(can_disable=True), 'routing-table': KeyInfo(can_disable=True), 'src-address': KeyInfo(can_disable=True), @@ -2010,6 +2013,8 @@ PATHS = { stratify_keys=('chain', ), fields={ 'action': KeyInfo(), + 'address-list': KeyInfo(can_disable=True), + 'address-list-timeout': KeyInfo(can_disable=True), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'connection-bytes': KeyInfo(can_disable=True), @@ -2020,7 +2025,7 @@ PATHS = { 'connection-state': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2037,11 +2042,11 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), + 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), + 'log': KeyInfo(can_disable=True), + 'log-prefix': KeyInfo(can_disable=True), 'new-connection-mark': KeyInfo(can_disable=True), 'new-dscp': KeyInfo(can_disable=True), 'new-mss': KeyInfo(can_disable=True), @@ -2064,6 +2069,7 @@ PATHS = { 'protocol': KeyInfo(can_disable=True), 'psd': KeyInfo(can_disable=True), 'random': KeyInfo(can_disable=True), + 'realm': KeyInfo(can_disable=True), 'route-dst': KeyInfo(can_disable=True), 'routing-mark': KeyInfo(can_disable=True), 'routing-table': KeyInfo(can_disable=True), @@ -2089,8 +2095,8 @@ PATHS = { stratify_keys=('chain', ), fields={ 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), + 'address-list': KeyInfo(can_disable=True), + 'address-list-timeout': KeyInfo(can_disable=True), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'connection-bytes': KeyInfo(can_disable=True), @@ -2099,7 +2105,7 @@ PATHS = { 'connection-rate': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2116,11 +2122,11 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), + 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), + 'log': KeyInfo(can_disable=True), + 'log-prefix': KeyInfo(can_disable=True), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -2134,9 +2140,10 @@ PATHS = { 'protocol': KeyInfo(can_disable=True), 'psd': KeyInfo(can_disable=True), 'random': KeyInfo(can_disable=True), + 'randomise-ports': KeyInfo(can_disable=True), 'realm': KeyInfo(can_disable=True), 'routing-mark': KeyInfo(can_disable=True), - 'same-not-by-dst': KeyInfo(), + 'same-not-by-dst': KeyInfo(can_disable=True), 'src-address': KeyInfo(can_disable=True), 'src-address-list': KeyInfo(can_disable=True), 'src-address-type': KeyInfo(can_disable=True), @@ -2157,12 +2164,12 @@ PATHS = { stratify_keys=('chain',), fields={ 'action': KeyInfo(), - 'address-list': KeyInfo(), - 'address-list-timeout': KeyInfo(), + 'address-list': KeyInfo(can_disable=True), + 'address-list-timeout': KeyInfo(can_disable=True), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2179,10 +2186,10 @@ PATHS = { 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), 'ipv4-options': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), + 'jump-target': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), + 'log': KeyInfo(can_disable=True), + 'log-prefix': KeyInfo(can_disable=True), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -2503,6 +2510,8 @@ PATHS = { stratify_keys=('chain', ), fields={ 'action': KeyInfo(), + 'address-list': KeyInfo(can_disable=True), + 'address-list-timeout': KeyInfo(can_disable=True), 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'connection-bytes': KeyInfo(can_disable=True), @@ -2512,7 +2521,7 @@ PATHS = { 'connection-state': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2528,10 +2537,10 @@ PATHS = { 'in-interface-list': KeyInfo(can_disable=True), 'ingress-priority': KeyInfo(can_disable=True), 'ipsec-policy': KeyInfo(can_disable=True), - 'jump-target': KeyInfo(), + 'jump-target': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(), - 'log-prefix': KeyInfo(), + 'log': KeyInfo(can_disable=False), + 'log-prefix': KeyInfo(can_disable=False), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -2573,7 +2582,7 @@ PATHS = { 'connection-state': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2647,7 +2656,7 @@ PATHS = { 'connection-state': KeyInfo(can_disable=True), 'connection-type': KeyInfo(can_disable=True), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2703,7 +2712,7 @@ PATHS = { 'chain': KeyInfo(), 'comment': KeyInfo(can_disable=True, remove_value=''), 'content': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'dscp': KeyInfo(can_disable=True), 'dst-address': KeyInfo(can_disable=True), 'dst-address-list': KeyInfo(can_disable=True), @@ -2796,7 +2805,7 @@ PATHS = { 'blackhole': KeyInfo(can_disable=True), 'check-gateway': KeyInfo(can_disable=True), 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'distance': KeyInfo(default=1), 'dst-address': KeyInfo(), 'gateway': KeyInfo(), @@ -3581,7 +3590,7 @@ PATHS = { 'cluster-id': KeyInfo(), 'comment': KeyInfo(), 'connect': KeyInfo(default=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'hold-time': KeyInfo(), 'input.accept-communities': KeyInfo(), 'input.accept-ext-communities': KeyInfo(), @@ -3640,7 +3649,7 @@ PATHS = { 'client-to-client-reflection': KeyInfo(), 'cluster-id': KeyInfo(can_disable=True), 'confederation': KeyInfo(can_disable=True), - 'disabled': KeyInfo(), + 'disabled': KeyInfo(default=False), 'ignore-as-path-len': KeyInfo(), 'name': KeyInfo(), 'out-filter': KeyInfo(), diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index 7587107..2f47af4 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -619,24 +619,28 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'input', 'comment': 'defconf', 'protocol': 'icmp', + 'disabled': False, }, { '.id': '*3', 'action': 'accept', 'chain': 'input', 'comment': 'defconf', + 'disabled': False, }, { '.id': '*4', 'action': 'accept', 'chain': 'input', 'comment': 'defconf', + 'disabled': False, }, { '.id': '*7', 'action': 'drop', 'chain': 'input', 'comment': 'defconf', + 'disabled': False, 'in-interface': 'wan', }, { @@ -645,6 +649,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'forward', 'comment': 'defconf', 'connection-state': 'established', + 'disabled': False, }, { '.id': '*9', @@ -652,6 +657,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'forward', 'comment': 'defconf', 'connection-state': 'related', + 'disabled': False, }, { '.id': '*A', @@ -659,6 +665,7 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'forward', 'comment': 'defconf', 'connection-status': 'invalid', + 'disabled': False, }, ]) self.assertEqual(result['match_count'], 3) diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index cd83d8a..3564668 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -198,6 +198,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'chain': 'input', 'in-interface-list': 'LAN', '!action': None, + '!address-list': None, + '!address-list-timeout': None, '!comment': None, '!connection-bytes': None, '!connection-limit': None, @@ -243,6 +245,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): '!protocol': None, '!psd': None, '!random': None, + '!realm': None, '!reject-with': None, '!routing-mark': None, '!routing-table': None, @@ -284,6 +287,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'chain': 'input', 'in-interface-list': 'LAN', 'action': None, + 'address-list': None, + 'address-list-timeout': None, 'comment': None, 'connection-bytes': None, 'connection-limit': None, @@ -329,6 +334,7 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'protocol': None, 'psd': None, 'random': None, + 'realm': None, 'reject-with': None, 'routing-mark': None, 'routing-table': None, From eda8f64e8dc17af0cd3c73d3dcf0040fd14f3d03 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 3 Dec 2023 13:18:18 +0100 Subject: [PATCH 187/365] Release 2.11.0. --- CHANGELOG.rst | 20 ++++++++++++++ changelogs/changelog.yaml | 27 +++++++++++++++++++ changelogs/fragments/2.11.0.yml | 1 - .../233-wireless-running-read-only.yml | 2 -- .../234-bugfixes-and-update-adaptations.yml | 5 ---- .../235-add-missing-dns-attributes.yml | 2 -- ...237-add-missing-ip-firewall-attributes.yml | 3 --- 7 files changed, 47 insertions(+), 13 deletions(-) delete mode 100644 changelogs/fragments/2.11.0.yml delete mode 100644 changelogs/fragments/233-wireless-running-read-only.yml delete mode 100644 changelogs/fragments/234-bugfixes-and-update-adaptations.yml delete mode 100644 changelogs/fragments/235-add-missing-dns-attributes.yml delete mode 100644 changelogs/fragments/237-add-missing-ip-firewall-attributes.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4b4eb0c..446fe8c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,26 @@ Community RouterOS Release Notes .. contents:: Topics +v2.11.0 +======= + +Release Summary +--------------- + +Feature and bugfix release. + +Minor Changes +------------- + +- api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) +- api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). +- api_info, api_modify - mark the ``interface wireless`` parameter ``running`` as read-only (https://github.com/ansible-collections/community.routeros/pull/233). +- api_info, api_modify - set the default value to ``false`` for the ``disabled`` parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). +- api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). +- api_modify - add missing attributes to the ``routing bgp connection`` path (https://github.com/ansible-collections/community.routeros/pull/234). +- api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 release) (https://github.com/ansible-collections/community.routeros/pull/234). +- api_modify - make ``/ip traffic-flow target`` a multiple value attribute (https://github.com/ansible-collections/community.routeros/pull/234). + v2.10.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index e3f69a4..f62ae62 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -254,6 +254,33 @@ releases: - 224-add-port-remote-access.yml - 227-add-upnp-graphing.yml release_date: '2023-10-08' + 2.11.0: + changes: + minor_changes: + - api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, + ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path + (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) + - api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, + ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path + (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). + - api_info, api_modify - mark the ``interface wireless`` parameter ``running`` + as read-only (https://github.com/ansible-collections/community.routeros/pull/233). + - api_info, api_modify - set the default value to ``false`` for the ``disabled`` + parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). + - api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add missing attributes to the ``routing bgp connection`` path + (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 release) + (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - make ``/ip traffic-flow target`` a multiple value attribute (https://github.com/ansible-collections/community.routeros/pull/234). + release_summary: Feature and bugfix release. + fragments: + - 2.11.0.yml + - 233-wireless-running-read-only.yml + - 234-bugfixes-and-update-adaptations.yml + - 235-add-missing-dns-attributes.yml + - 237-add-missing-ip-firewall-attributes.yml + release_date: '2023-12-03' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.11.0.yml b/changelogs/fragments/2.11.0.yml deleted file mode 100644 index 80287c3..0000000 --- a/changelogs/fragments/2.11.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature and bugfix release. diff --git a/changelogs/fragments/233-wireless-running-read-only.yml b/changelogs/fragments/233-wireless-running-read-only.yml deleted file mode 100644 index a69aa58..0000000 --- a/changelogs/fragments/233-wireless-running-read-only.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - mark the ``interface wireless`` parameter ``running`` as read-only (https://github.com/ansible-collections/community.routeros/pull/233). diff --git a/changelogs/fragments/234-bugfixes-and-update-adaptations.yml b/changelogs/fragments/234-bugfixes-and-update-adaptations.yml deleted file mode 100644 index 8105c1d..0000000 --- a/changelogs/fragments/234-bugfixes-and-update-adaptations.yml +++ /dev/null @@ -1,5 +0,0 @@ -minor_changes: - - api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - make ``/ip traffic-flow target`` a multiple value attribute (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 release) (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - add missing attributes to the ``routing bgp connection`` path (https://github.com/ansible-collections/community.routeros/pull/234). diff --git a/changelogs/fragments/235-add-missing-dns-attributes.yml b/changelogs/fragments/235-add-missing-dns-attributes.yml deleted file mode 100644 index f2bf2f5..0000000 --- a/changelogs/fragments/235-add-missing-dns-attributes.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) diff --git a/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml b/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml deleted file mode 100644 index 677fef5..0000000 --- a/changelogs/fragments/237-add-missing-ip-firewall-attributes.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). - - api_info, api_modify - set the default value to ``false`` for the ``disabled`` parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). From ac89aa0ab7f37f498dbc5a811e59504cab42c5e2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 7 Dec 2023 08:01:47 +0100 Subject: [PATCH 188/365] Allow to declare some versions as unsupported, and to provide an explicit message. (#238) --- plugins/module_utils/_api_data.py | 22 +++++++++++++++------- plugins/modules/api_info.py | 8 ++++++-- plugins/modules/api_modify.py | 8 ++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 747017a..28b0f06 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -49,23 +49,31 @@ class APIData(object): break self._current = None if self.needs_version else self.unversioned + def _select(self, data, api_version): + if data is None: + self._current = None + return False, None + if isinstance(data, str): + self._current = None + return False, data + self._current = data.specialize_for_version(api_version) + return self._current.fully_understood, None + def provide_version(self, version): if not self.needs_version: - return self.unversioned.fully_understood + return self.unversioned.fully_understood, None api_version = LooseVersion(version) if self.unversioned is not None: self._current = self.unversioned.specialize_for_version(api_version) - return self._current.fully_understood + return self._current.fully_understood, None for other_version, comparator, data in self.versioned: if other_version == '*' and comparator == '*': - self._current = data.specialize_for_version(api_version) - return self._current.fully_understood + return self._select(data, api_version) other_api_version = LooseVersion(other_version) if _compare(api_version, other_api_version, comparator): - self._current = data.specialize_for_version(api_version) - return self._current.fully_understood + return self._select(data, api_version) self._current = None - return False + return False, None def get_data(self): if self._current is None: diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5a66ace..315c75f 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -350,8 +350,12 @@ def main(): module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) if versioned_path_info.needs_version: api_version = get_api_version(api) - if not versioned_path_info.provide_version(api_version): - module.fail_json(msg='Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)) + supported, not_supported_msg = versioned_path_info.provide_version(api_version) + if not supported: + msg = 'Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version) + if not_supported_msg: + msg = '{0}: {1}'.format(msg, not_supported_msg) + module.fail_json(msg=msg) path_info = versioned_path_info.get_data() handle_disabled = module.params['handle_disabled'] diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index bb06315..07ec5b0 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -1133,8 +1133,12 @@ def main(): versioned_path_info = PATHS.get(tuple(path)) if versioned_path_info.needs_version: api_version = get_api_version(api) - if not versioned_path_info.provide_version(api_version): - module.fail_json(msg='Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)) + supported, not_supported_msg = versioned_path_info.provide_version(api_version) + if not supported: + msg = 'Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version) + if not_supported_msg: + msg = '{0}: {1}'.format(msg, not_supported_msg) + module.fail_json(msg=msg) path_info = versioned_path_info.get_data() backend = get_backend(path_info) From 482e5b2b7e43104aeb1cdc5badc7fda855b96631 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 07:14:45 +0100 Subject: [PATCH 189/365] Bump actions/setup-python from 4 to 5 (#240) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ee.yml | 2 +- .github/workflows/extra-tests.yml | 2 +- .github/workflows/import-galaxy.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 82e2843..523efaf 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -86,7 +86,7 @@ jobs: path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml index 98a1e70..54872aa 100644 --- a/.github/workflows/extra-tests.yml +++ b/.github/workflows/extra-tests.yml @@ -31,7 +31,7 @@ jobs: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index 5825597..9d80ef1 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -28,7 +28,7 @@ jobs: path: ./checkout - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' @@ -69,7 +69,7 @@ jobs: - build-collection steps: - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.11' From c5e51f9a93742ba1cf094b041c032048c01aa0f8 Mon Sep 17 00:00:00 2001 From: Yuri Timenkov Date: Thu, 14 Dec 2023 07:51:48 +0100 Subject: [PATCH 190/365] Support for WifiWave2. (#226) * Support for WifiWave2. Added configuration profiles to configure Mikrotik APs which have only WifiWave2 package. * Addressed review comments 1. Sorted lexicographically new entries 2. Added versioning * Added few related paths * Fixed typos * Lowered min version * Added wifiwave2 interfaces * Added upper version limit to WifiWave2 According to the documentation, new RouterOS version uses another package. * Addressed review comments --- .../fragments/226-support-for-WifiWave2.yml | 2 + plugins/module_utils/_api_data.py | 300 +++++++++++++++++- plugins/modules/api_info.py | 12 + plugins/modules/api_modify.py | 14 +- 4 files changed, 326 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/226-support-for-WifiWave2.yml diff --git a/changelogs/fragments/226-support-for-WifiWave2.yml b/changelogs/fragments/226-support-for-WifiWave2.yml new file mode 100644 index 0000000..fd98793 --- /dev/null +++ b/changelogs/fragments/226-support-for-WifiWave2.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 28b0f06..3abd0f1 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -44,7 +44,7 @@ class APIData(object): # Mark as 'fully understood' if it is for at least one version self.fully_understood = False for dummy, dummy, unversioned in self.versioned: - if unversioned.fully_understood: + if unversioned and not isinstance(unversioned, str) and unversioned.fully_understood: self.fully_understood = True break self._current = None if self.needs_version else self.unversioned @@ -1468,6 +1468,304 @@ PATHS = { }, ), ), + ('interface', 'wifiwave2'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + required_one_of=[['default-name', 'master-interface']], + fields={ + 'aaa': KeyInfo(), + 'arp-timeout': KeyInfo(default='auto'), + 'arp': KeyInfo(default='enabled'), + 'channel': KeyInfo(), + 'configuration': KeyInfo(), + 'datapath': KeyInfo(), + 'default-name': KeyInfo(), + 'disable-running-check': KeyInfo(default=False), + 'interworking': KeyInfo(), + 'l2mtu': KeyInfo(default=1600), + 'mac-address': KeyInfo(), + 'master-interface': KeyInfo(), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'security': KeyInfo(), + 'steering': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'aaa'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'called-format': KeyInfo(can_disable=True), + 'calling-format': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=True), + 'interim-update': KeyInfo(can_disable=True), + 'mac-caching': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'nas-identifier': KeyInfo(can_disable=True), + 'password-format': KeyInfo(can_disable=True), + 'username-format': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'access-list'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(can_disable=True), + 'allow-signal-out-of-range': KeyInfo(can_disable=True), + 'client-isolation': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=True), + 'interface': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True), + 'mac-address-mask': KeyInfo(can_disable=True), + 'passphrase': KeyInfo(can_disable=True), + 'radius-accounting': KeyInfo(can_disable=True), + 'signal-range': KeyInfo(can_disable=True), + 'ssid-regexp': KeyInfo(), + 'time': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'cap'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'caps-man-addresses': KeyInfo(default=''), + 'caps-man-certificate-common-names': KeyInfo(default=''), + 'caps-man-names': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'discovery-interfaces': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'lock-to-caps-man': KeyInfo(default=False), + 'slaves-datapath': KeyInfo(), + 'slaves-static': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'capsman'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'ca-certificate': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'enabled': KeyInfo(default=False), + 'package-path': KeyInfo(default=''), + 'require-peer-certificate': KeyInfo(default=False), + 'upgrade-policy': KeyInfo(default='none'), + 'interfaces': KeyInfo(default=''), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'channel'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'band': KeyInfo(), + 'frequency': KeyInfo(), + 'name': KeyInfo(), + 'secondary-frequency': KeyInfo(), + 'skip-dfs-channels': KeyInfo(default='disabled'), + 'width': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'configuration'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'aaa': KeyInfo(), + 'antenna-gain': KeyInfo(), + 'beacon-interval': KeyInfo(default=100), + 'chains': KeyInfo(), + 'channel': KeyInfo(), + 'country': KeyInfo(default='United States'), + 'datapath': KeyInfo(), + 'dtim-period': KeyInfo(default=1), + 'hide-ssid': KeyInfo(default=False), + 'interworking': KeyInfo(), + 'manager': KeyInfo(), + 'mode': KeyInfo(default='ap'), + 'name': KeyInfo(), + 'security': KeyInfo(), + 'ssid': KeyInfo(), + 'steering': KeyInfo(), + 'tx-chains': KeyInfo(), + 'tx-power': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'datapath'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'bridge': KeyInfo(), + 'bridge-cost': KeyInfo(), + 'bridge-horizon': KeyInfo(), + 'client-isolation': KeyInfo(default=False), + 'interface-list': KeyInfo(), + 'name': KeyInfo(), + 'openflow-switch': KeyInfo(), + 'vlan-id': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'interworking'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + '3gpp-info': KeyInfo(), + 'authentication-types': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-capabilities': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'domain-names': KeyInfo(), + 'esr': KeyInfo(), + 'hessid': KeyInfo(), + 'hotspot20': KeyInfo(), + 'hotspot20-dgaf': KeyInfo(), + 'internet': KeyInfo(), + 'ipv4-availability': KeyInfo(), + 'ipv6-availability': KeyInfo(), + 'name': KeyInfo(), + 'network-type': KeyInfo(), + 'operational-classes': KeyInfo(), + 'operator-names': KeyInfo(), + 'realms': KeyInfo(), + 'roaming-ois': KeyInfo(), + 'uesa': KeyInfo(), + 'venue': KeyInfo(), + 'venue-names': KeyInfo(), + 'wan-at-capacity': KeyInfo(), + 'wan-downlink': KeyInfo(), + 'wan-downlink-load': KeyInfo(), + 'wan-measurement-duration': KeyInfo(), + 'wan-status': KeyInfo(), + 'wan-symmetric': KeyInfo(), + 'wan-uplink': KeyInfo(), + 'wan-uplink-load': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'provisioning'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('action', ), + fields={ + 'action': KeyInfo(default='none'), + 'address-ranges': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'common-name-regexp': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'identity-regexp': KeyInfo(), + 'master-configuration': KeyInfo(), + 'name-format': KeyInfo(), + 'radio-mac': KeyInfo(), + 'slave-configurations': KeyInfo(), + 'supported-bands': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'security'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'authentication-types': KeyInfo(), + 'connect-group': KeyInfo(can_disable=True), + 'connect-priority': KeyInfo(), + 'dh-groups': KeyInfo(), + 'disable-pmkid': KeyInfo(default=False), + 'eap-accounting': KeyInfo(default=False), + 'eap-anonymous-identity': KeyInfo(), + 'eap-certificate-mode': KeyInfo(default='dont-verify-certificate'), + 'eap-methods': KeyInfo(), + 'eap-password': KeyInfo(), + 'eap-tls-certificate': KeyInfo(), + 'eap-username': KeyInfo(), + 'encryption': KeyInfo(default='ccmp'), + 'ft-mobility-domain': KeyInfo(default=0xADC4), + 'ft-nas-identifier': KeyInfo(), + 'ft-over-ds': KeyInfo(default=False), + 'ft-preserve-vlanid': KeyInfo(default=True), + 'ft-r0-key-lifetime': KeyInfo(default='600000s'), + 'ft-reassociation-deadline': KeyInfo(default='20s'), + 'ft': KeyInfo(default=False), + 'group-encryption': KeyInfo(default='ccmp'), + 'group-key-update': KeyInfo(default='24h'), + 'management-encryption': KeyInfo(default='cmac'), + 'management-protection': KeyInfo(), + 'name': KeyInfo(), + 'owe-transition-interface': KeyInfo(), + 'passphrase': KeyInfo(default=''), + 'sae-anti-clogging-threshold': KeyInfo(can_disable=True), + 'sae-max-failure-rate': KeyInfo(can_disable=True), + 'sae-pwe': KeyInfo(default='both'), + 'wps': KeyInfo(default='push-button'), + }, + )), + ], + ), + ('interface', 'wifiwave2', 'steering'): APIData( + versioned=[ + ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), + ('7.8', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'neighbor-group': KeyInfo(), + 'rrm': KeyInfo(), + 'wnm': KeyInfo(), + }, + )), + ], + ), ('interface', 'wireguard'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 315c75f..2b5a2c9 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -78,6 +78,18 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wifiwave2 + - interface wifiwave2 aaa + - interface wifiwave2 access-list + - interface wifiwave2 cap + - interface wifiwave2 capsman + - interface wifiwave2 channel + - interface wifiwave2 configuration + - interface wifiwave2 datapath + - interface wifiwave2 interworking + - interface wifiwave2 provisioning + - interface wifiwave2 security + - interface wifiwave2 steering - interface wireguard - interface wireguard peers - interface wireless diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 07ec5b0..2b5229b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -87,6 +87,18 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wifiwave2 + - interface wifiwave2 aaa + - interface wifiwave2 access-list + - interface wifiwave2 cap + - interface wifiwave2 capsman + - interface wifiwave2 channel + - interface wifiwave2 configuration + - interface wifiwave2 datapath + - interface wifiwave2 interworking + - interface wifiwave2 provisioning + - interface wifiwave2 security + - interface wifiwave2 steering - interface wireguard - interface wireguard peers - interface wireless @@ -1096,7 +1108,7 @@ def has_backend(versioned_path_info): if versioned_path_info.versioned is not None: for dummy, dummy, unversioned in versioned_path_info.versioned: - if get_backend(unversioned) is not None: + if unversioned and not isinstance(unversioned, str) and get_backend(unversioned) is not None: return True return False From 332955aff57130506ccf4d04555be3b0a10c3af8 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 14 Dec 2023 07:52:37 +0100 Subject: [PATCH 191/365] Add support for the "tx-power" wireless parameter (#239) Signed-off-by: Michael Hanselmann --- changelogs/fragments/239-wireless-tx-power.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/239-wireless-tx-power.yml diff --git a/changelogs/fragments/239-wireless-tx-power.yml b/changelogs/fragments/239-wireless-tx-power.yml new file mode 100644 index 0000000..560639b --- /dev/null +++ b/changelogs/fragments/239-wireless-tx-power.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``tx-power`` attribute in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 3abd0f1..435e86b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1882,6 +1882,7 @@ PATHS = { 'supported-rates-b': KeyInfo(), 'tdma-period-size': KeyInfo(default=2), 'tx-chains': KeyInfo(), + 'tx-power': KeyInfo(default=''), 'tx-power-mode': KeyInfo(default='default'), 'update-stats-interval': KeyInfo(default='disabled'), 'vlan-id': KeyInfo(default=1), From 9b1b28599fa8718158417f75d70080d20c242664 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Dec 2023 07:53:29 +0100 Subject: [PATCH 192/365] Next release will be 2.12.0. --- changelogs/fragments/2.12.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.12.0.yml diff --git a/changelogs/fragments/2.12.0.yml b/changelogs/fragments/2.12.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/2.12.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index 1a7be77..97d5a33 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.11.0 +version: 2.12.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From a1492b440580a1a6ae5f01bf5a7dbabb60f26ede Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 18 Dec 2023 19:28:45 +0100 Subject: [PATCH 193/365] Bump both artifact actions to v4. --- .github/workflows/import-galaxy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index 9d80ef1..a32f565 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -57,7 +57,7 @@ jobs: run: mkdir ./artifact && mv ./checkout/${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz ./artifact - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} path: ./artifact/ @@ -80,7 +80,7 @@ jobs: run: pip install galaxy-importer --disable-pip-version-check - name: Download artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} From 4fff1f1bbb68bb219da02dca79a8fe1fbd9d500f Mon Sep 17 00:00:00 2001 From: derdeagle Date: Tue, 26 Dec 2023 16:46:21 +0100 Subject: [PATCH 194/365] Add '/interface ovpn-client' path (#244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #242: Add '/interface ovpn-client' path * Add changelog fragment * Update changelogs/fragments/244-add-interface-ovpn-client-path.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Johannes Münch Co-authored-by: Felix Fontein --- .../244-add-interface-ovpn-client-path.yml | 2 ++ plugins/module_utils/_api_data.py | 29 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 33 insertions(+) create mode 100644 changelogs/fragments/244-add-interface-ovpn-client-path.yml diff --git a/changelogs/fragments/244-add-interface-ovpn-client-path.yml b/changelogs/fragments/244-add-interface-ovpn-client-path.yml new file mode 100644 index 0000000..15dbcd9 --- /dev/null +++ b/changelogs/fragments/244-add-interface-ovpn-client-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, https://github.com/ansible-collections/community.routeros/pull/244). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 435e86b..4c3e311 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1413,6 +1413,35 @@ PATHS = { }, ), ), + ('interface', 'ovpn-client'): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'add-default-route': KeyInfo(default=False), + 'auth': KeyInfo(default='sha1'), + 'certificate': KeyInfo(), + 'cipher': KeyInfo(default='blowfish128'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connect-to': KeyInfo(), + 'disabled': KeyInfo(default=True), + 'disconnect-notify': KeyInfo(), + 'mac-address': KeyInfo(), + 'max-mtu': KeyInfo(default=1500), + 'mode': KeyInfo(default='ip'), + 'name': KeyInfo(), + 'password': KeyInfo(), + 'port': KeyInfo(default=1194), + 'profile': KeyInfo(default='default'), + 'protocol': KeyInfo(default='tcp'), + 'route-nopull': KeyInfo(default=False), + 'tls-version': KeyInfo(default='any'), + 'use-peer-dns': KeyInfo(default=True), + 'user': KeyInfo(), + 'verify-server-certificate': KeyInfo(default=False), + }, + ), + ), ('interface', 'ovpn-server', 'server'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 2b5a2c9..4e28c72 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -71,6 +71,7 @@ options: - interface l2tp-server server - interface list - interface list member + - interface ovpn-client - interface ovpn-server server - interface ppp-client - interface pppoe-client diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 2b5229b..fa7551e 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -80,6 +80,7 @@ options: - interface l2tp-server server - interface list - interface list member + - interface ovpn-client - interface ovpn-server server - interface ppp-client - interface pppoe-client From e4e5f64b46790aad55820e1788ae25eb2679c7af Mon Sep 17 00:00:00 2001 From: derdeagle Date: Tue, 26 Dec 2023 16:46:40 +0100 Subject: [PATCH 195/365] Add '/routing bgp template' path (#243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add '/routing bgp template' path * Add changelog fragment * Update changelogs/fragments/243-add-routing-bgp-template-path.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Johannes Münch Co-authored-by: Felix Fontein --- .../243-add-routing-bgp-template-path.yml | 2 + plugins/module_utils/_api_data.py | 50 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 54 insertions(+) create mode 100644 changelogs/fragments/243-add-routing-bgp-template-path.yml diff --git a/changelogs/fragments/243-add-routing-bgp-template-path.yml b/changelogs/fragments/243-add-routing-bgp-template-path.yml new file mode 100644 index 0000000..c1cf627 --- /dev/null +++ b/changelogs/fragments/243-add-routing-bgp-template-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 4c3e311..64bace4 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3999,6 +3999,56 @@ PATHS = { }, ), ), + ('routing', 'bgp', 'template'): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'add-path-out': KeyInfo(), + 'address-families': KeyInfo(default='ip'), + 'as': KeyInfo(), + 'as-override': KeyInfo(default=False), + 'cisco-vpls-nlri-len-fmt': KeyInfo(), + 'cluster-id': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'hold-time': KeyInfo(default='3m'), + 'input.accept-communities': KeyInfo(), + 'input.accept-ext-communities': KeyInfo(), + 'input.accept-large-communities': KeyInfo(), + 'input.accept-unknown': KeyInfo(), + 'input.accept-nlri': KeyInfo(), + 'input.affinity': KeyInfo(), + 'input.allow-as': KeyInfo(), + 'input.filter': KeyInfo(), + 'input.ignore-as-path-len': KeyInfo(default=False), + 'input.limit-nlri-diversity': KeyInfo(), + 'input.limit-process-routes-ipv4': KeyInfo(), + 'input.limit-process-routes-ipv6': KeyInfo(), + 'keepalive-time': KeyInfo(default='3m'), + 'multihop': KeyInfo(default=False), + 'name': KeyInfo(), + 'nexthop-choice': KeyInfo(default='default'), + 'output.affinity': KeyInfo(), + 'output.default-originate': KeyInfo(default='never'), + 'output.default-prepent': KeyInfo(), + 'output.filter-chain': KeyInfo(), + 'output.filter-select': KeyInfo(), + 'output.keep-sent-attributes': KeyInfo(default=False), + 'output.network': KeyInfo(), + 'output.no-client-to-client-reflection': KeyInfo(), + 'output.no-early-cut': KeyInfo(), + 'output.redistribute': KeyInfo(), + 'remove-private-as': KeyInfo(default=False), + 'router-id': KeyInfo(default='main'), + 'routing-table': KeyInfo(default='main'), + 'save-to': KeyInfo(), + 'templates': KeyInfo(), + 'use-bfd': KeyInfo(default=False), + 'vrf': KeyInfo(default='main'), + }, + ), + ), ('system', 'logging', 'action'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 4e28c72..2609373 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -171,6 +171,7 @@ options: - radius incoming - routing bgp connection - routing bgp instance + - routing bgp template - routing filter rule - routing filter select-rule - routing id diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index fa7551e..8bd01e5 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -180,6 +180,7 @@ options: - radius incoming - routing bgp connection - routing bgp instance + - routing bgp template - routing filter rule - routing filter select-rule - routing id From 1d6feda0b7f5cb44ba84fe90b7568afe2e577623 Mon Sep 17 00:00:00 2001 From: derdeagle Date: Thu, 28 Dec 2023 08:35:28 +0100 Subject: [PATCH 196/365] Add the 'radius' path (#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #241: Add the 'radius' path * Add changelog fragment --------- Co-authored-by: Johannes Münch --- changelogs/fragments/245-add-radius-path.yml | 2 ++ plugins/module_utils/_api_data.py | 22 ++++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 26 insertions(+) create mode 100644 changelogs/fragments/245-add-radius-path.yml diff --git a/changelogs/fragments/245-add-radius-path.yml b/changelogs/fragments/245-add-radius-path.yml new file mode 100644 index 0000000..47572fd --- /dev/null +++ b/changelogs/fragments/245-add-radius-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, https://github.com/ansible-collections/community.routeros/pull/245). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 64bace4..c0cdb81 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3228,6 +3228,28 @@ PATHS = { }, ), ), + ('radius', ): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'accounting-backup': KeyInfo(default=False), + 'accounting-port': KeyInfo(default=1813), + 'address': KeyInfo(default='0.0.0.0'), + 'authentication-port': KeyInfo(default=1812), + 'called-id': KeyInfo(), + 'certificate': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'domain': KeyInfo(), + 'protocol': KeyInfo(default='udp'), + 'realm': KeyInfo(), + 'secret': KeyInfo(), + 'service': KeyInfo(), + 'src-address': KeyInfo(default='0.0.0.0'), + 'timeout': KeyInfo(default='300ms'), + }, + ), + ), ('radius', 'incoming'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 2609373..5377998 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -168,6 +168,7 @@ options: - ppp profile - queue interface - queue tree + - radius - radius incoming - routing bgp connection - routing bgp instance diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 8bd01e5..afc58cd 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -177,6 +177,7 @@ options: - ppp profile - queue interface - queue tree + - radius - radius incoming - routing bgp connection - routing bgp instance From 9c75b9c5cdae74ca19fad319fc9a4ed1abb7ffb0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 6 Jan 2024 08:47:34 +0100 Subject: [PATCH 197/365] Fix module default group example. --- docs/docsite/rst/api-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index cb16fe8..b24ec70 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -73,7 +73,7 @@ To avoid having to specify common parameters for all the API based modules in ev hosts: localhost gather_facts: false module_defaults: - group/community.routeros.api + group/community.routeros.api: hostname: 192.168.1.1 password: admin username: test1234 From 56ce47aef5dd2f9129debe807bab078382879043 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 6 Jan 2024 09:38:12 +0100 Subject: [PATCH 198/365] Update docs (#248) * Add reference to module defaults groups docs. * Fix bad quote. --- docs/docsite/rst/api-guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index b24ec70..6140d81 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -64,7 +64,7 @@ Check out the documentation of the :ansplugin:`community.routeros.api module `: .. code-block:: yaml+jinja @@ -85,7 +85,7 @@ To avoid having to specify common parameters for all the API based modules in ev # If you are using your own PKI, specify the path to your CA certificate here: # ca_path: /path/to/ca-certificate.pem tasks: - - name: Gather facts" + - name: Gather facts community.routeros.api_facts: - name: Get "ip address print" From 79dabbb67ea138522920d8035f1209bffa70d7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Sat, 6 Jan 2024 16:52:17 +0100 Subject: [PATCH 199/365] #162: Add 'routing rule' path (#246) --- .../fragments/246-add-routing-rule-path.yml | 2 ++ plugins/module_utils/_api_data.py | 18 ++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 22 insertions(+) create mode 100644 changelogs/fragments/246-add-routing-rule-path.yml diff --git a/changelogs/fragments/246-add-routing-rule-path.yml b/changelogs/fragments/246-add-routing-rule-path.yml new file mode 100644 index 0000000..53c6263 --- /dev/null +++ b/changelogs/fragments/246-add-routing-rule-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, https://github.com/ansible-collections/community.routeros/pull/246). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index c0cdb81..8c74952 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -960,6 +960,24 @@ PATHS = { }, ), ), + ('routing', 'rule'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dst-address': KeyInfo(can_disable=True), + 'interface': KeyInfo(can_disable=True), + 'min-prefix': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'table': KeyInfo(can_disable=True), + }, + )), + ], + ), ('routing', 'table'): APIData( versioned=[ ('7', '>=', VersionedAPIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5377998..6eea5e8 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -185,6 +185,7 @@ options: - routing pimsm interface-template - routing rip - routing ripng + - routing rule - routing table - snmp - snmp community diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index afc58cd..a683c2a 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -194,6 +194,7 @@ options: - routing pimsm interface-template - routing rip - routing ripng + - routing rule - routing table - snmp - snmp community From d5a2686d2093ea82abecaa553b045f46a2242a61 Mon Sep 17 00:00:00 2001 From: Tim de Boer Date: Sun, 7 Jan 2024 14:04:20 +0100 Subject: [PATCH 200/365] Changed primary key of 'tool netwatch' (#247) * Changed primary key of 'tool netwatch' * Removed the primary key after discussion on PR #247 * Added changelog fragment --- .../fragments/247-removed-primary-key-host-in-tool-netwatch.yml | 2 ++ plugins/module_utils/_api_data.py | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml diff --git a/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml b/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml new file mode 100644 index 0000000..7b7e858 --- /dev/null +++ b/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` path (https://github.com/ansible-collections/community.routeros/pull/248). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 8c74952..5518abd 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3670,7 +3670,6 @@ PATHS = { versioned=[ ('7', '>=', VersionedAPIData( fully_understood=True, - primary_keys=('name', ), fields={ 'certificate': KeyInfo(), 'check-certificate': KeyInfo(), From 3777b283b214dc41349fc4887e5f753537933642 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 13 Jan 2024 17:08:19 +0100 Subject: [PATCH 201/365] Use import galaxy workflow from https://github.com/ansible-collections/community.docker/pull/754. (#249) --- .github/workflows/import-galaxy.yml | 90 +++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index a32f565..d5bcb5b 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later name: import-galaxy -on: +'on': # Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests push: branches: @@ -12,11 +12,6 @@ on: - stable-* pull_request: -env: - # Adjust this to your collection - NAMESPACE: community - COLLECTION_NAME: routeros - jobs: build-collection: name: Build collection artifact @@ -30,23 +25,46 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - - name: Install ansible-core + - name: Install ansible-core devel run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - name: Make sure galaxy.yml has version entry - run: >- - python -c - 'import yaml ; - f = open("galaxy.yml", "rb") ; - data = yaml.safe_load(f) ; - f.close() ; - data["version"] = data.get("version") or "0.0.1" ; - f = open("galaxy.yml", "wb") ; - f.write(yaml.dump(data).encode("utf-8")) ; - f.close() ; - ' + shell: python + id: collection-metadata + run: | + import os + import yaml + + def set_output(name, value): + with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as f: + f.write(f'{name}={value}{os.linesep}') + + # Make sure galaxy.yml contains a version + with open('galaxy.yml', 'rb') as f: + data = yaml.safe_load(f) ; + data['version'] = data.get('version') or '0.0.1' + with open('galaxy.yml', 'w', encoding='utf-8') as f: + f.write(yaml.dump(data)) + + # Create Galaxy requirements file + if data.get('dependencies'): + reqs = dict(collections=[]) + for collection, version in sorted(data['dependencies'].items()): + reqs['collections'].append(dict( + name=collection, + source='https://galaxy.ansible.com', + version=version, + )) + with open('../requirements.yml', 'w', encoding='utf-8') as f: + f.write(yaml.dump(reqs)) + + # Extract namespace and collection name + set_output('name', data['name']) + set_output('namespace', data['namespace']) + set_output('version', data['version']) + set_output('filename', f"{data['namespace']}-{data['name']}-{data['version']}.tar.gz") working-directory: ./checkout - name: Build collection @@ -54,12 +72,19 @@ jobs: working-directory: ./checkout - name: Copy artifact into subdirectory - run: mkdir ./artifact && mv ./checkout/${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz ./artifact + shell: bash + run: | + set -e + mkdir artifact + mv checkout/${{ steps.collection-metadata.outputs.filename }} artifact/ + if [ -f requirements.yml ]; then + mv requirements.yml artifact/ + fi - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} + name: collection-build-${{ github.sha }} path: ./artifact/ import-galaxy: @@ -71,9 +96,12 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: + # Currently requirements-parser is incompatible with Python 3.12 + # (https://github.com/madpah/requirements-parser/issues/88), so we + # have to stick to Python 3.11 for now... python-version: '3.11' - - name: Install ansible-core + - name: Install ansible-core devel run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - name: Install galaxy-importer @@ -82,7 +110,21 @@ jobs: - name: Download artifact uses: actions/download-artifact@v4 with: - name: ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-${{ github.sha }} + name: collection-build-${{ github.sha }} + + - name: List files + shell: bash + run: | + ls -la + + - name: Install collection dependencies + shell: bash + run: | + if [ -f requirements.yml ]; then + ansible-galaxy collection install --pre --requirements-file requirements.yml + else + echo "Collection has no dependencies." + fi - name: Run Galaxy importer - run: python -m galaxy_importer.main ${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}-*.tar.gz + run: python -m galaxy_importer.main *-*-*.tar.gz From b56ba388f9db7d83087579012ac2c8e8e4f8ce70 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 17 Jan 2024 23:09:09 +0100 Subject: [PATCH 202/365] Simplifiy workflows. (#251) --- .github/workflows/import-galaxy.yml | 118 +--------------------------- .github/workflows/reuse.yml | 9 +-- 2 files changed, 6 insertions(+), 121 deletions(-) diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml index d5bcb5b..0c0ee40 100644 --- a/.github/workflows/import-galaxy.yml +++ b/.github/workflows/import-galaxy.yml @@ -13,118 +13,8 @@ name: import-galaxy pull_request: jobs: - build-collection: - name: Build collection artifact - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v4 - with: - path: ./checkout - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Install ansible-core devel - run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - - - name: Make sure galaxy.yml has version entry - shell: python - id: collection-metadata - run: | - import os - import yaml - - def set_output(name, value): - with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as f: - f.write(f'{name}={value}{os.linesep}') - - # Make sure galaxy.yml contains a version - with open('galaxy.yml', 'rb') as f: - data = yaml.safe_load(f) ; - data['version'] = data.get('version') or '0.0.1' - with open('galaxy.yml', 'w', encoding='utf-8') as f: - f.write(yaml.dump(data)) - - # Create Galaxy requirements file - if data.get('dependencies'): - reqs = dict(collections=[]) - for collection, version in sorted(data['dependencies'].items()): - reqs['collections'].append(dict( - name=collection, - source='https://galaxy.ansible.com', - version=version, - )) - with open('../requirements.yml', 'w', encoding='utf-8') as f: - f.write(yaml.dump(reqs)) - - # Extract namespace and collection name - set_output('name', data['name']) - set_output('namespace', data['namespace']) - set_output('version', data['version']) - set_output('filename', f"{data['namespace']}-{data['name']}-{data['version']}.tar.gz") - working-directory: ./checkout - - - name: Build collection - run: ansible-galaxy collection build - working-directory: ./checkout - - - name: Copy artifact into subdirectory - shell: bash - run: | - set -e - mkdir artifact - mv checkout/${{ steps.collection-metadata.outputs.filename }} artifact/ - if [ -f requirements.yml ]; then - mv requirements.yml artifact/ - fi - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: collection-build-${{ github.sha }} - path: ./artifact/ - import-galaxy: - name: Import artifact with Galaxy importer - runs-on: ubuntu-latest - needs: - - build-collection - steps: - - name: Set up Python - uses: actions/setup-python@v5 - with: - # Currently requirements-parser is incompatible with Python 3.12 - # (https://github.com/madpah/requirements-parser/issues/88), so we - # have to stick to Python 3.11 for now... - python-version: '3.11' - - - name: Install ansible-core devel - run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - - - name: Install galaxy-importer - run: pip install galaxy-importer --disable-pip-version-check - - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: collection-build-${{ github.sha }} - - - name: List files - shell: bash - run: | - ls -la - - - name: Install collection dependencies - shell: bash - run: | - if [ -f requirements.yml ]; then - ansible-galaxy collection install --pre --requirements-file requirements.yml - else - echo "Collection has no dependencies." - fi - - - name: Run Galaxy importer - run: python -m galaxy_importer.main *-*-*.tar.gz + permissions: + contents: read + name: Test to import built collection artifact with Galaxy importer + uses: ansible-community/github-action-test-galaxy-import/.github/workflows/test-galaxy-import.yml@main diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index cd342bd..bde03ff 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -23,10 +23,5 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install dependencies - run: | - pip install reuse - - - name: Check REUSE compliance - run: | - reuse lint + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v2 From d1401bdb58ab9bc4eac67241f14b09f4ead5c339 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 Jan 2024 08:47:39 +0100 Subject: [PATCH 203/365] Release 2.12.0. --- CHANGELOG.rst | 19 ++++++++++++++ changelogs/changelog.yaml | 26 +++++++++++++++++++ changelogs/fragments/2.12.0.yml | 1 - .../fragments/226-support-for-WifiWave2.yml | 2 -- .../fragments/239-wireless-tx-power.yml | 2 -- .../243-add-routing-bgp-template-path.yml | 2 -- .../244-add-interface-ovpn-client-path.yml | 2 -- changelogs/fragments/245-add-radius-path.yml | 2 -- .../fragments/246-add-routing-rule-path.yml | 2 -- ...oved-primary-key-host-in-tool-netwatch.yml | 2 -- 10 files changed, 45 insertions(+), 15 deletions(-) delete mode 100644 changelogs/fragments/2.12.0.yml delete mode 100644 changelogs/fragments/226-support-for-WifiWave2.yml delete mode 100644 changelogs/fragments/239-wireless-tx-power.yml delete mode 100644 changelogs/fragments/243-add-routing-bgp-template-path.yml delete mode 100644 changelogs/fragments/244-add-interface-ovpn-client-path.yml delete mode 100644 changelogs/fragments/245-add-radius-path.yml delete mode 100644 changelogs/fragments/246-add-routing-rule-path.yml delete mode 100644 changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 446fe8c..c1932ad 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,25 @@ Community RouterOS Release Notes .. contents:: Topics +v2.12.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, https://github.com/ansible-collections/community.routeros/pull/244). +- api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, https://github.com/ansible-collections/community.routeros/pull/245). +- api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, https://github.com/ansible-collections/community.routeros/pull/246). +- api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). +- api_info, api_modify - add support for the ``tx-power`` attribute in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). +- api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` path (https://github.com/ansible-collections/community.routeros/pull/248). +- api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). + v2.11.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index f62ae62..6461aa6 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -281,6 +281,32 @@ releases: - 235-add-missing-dns-attributes.yml - 237-add-missing-ip-firewall-attributes.yml release_date: '2023-12-03' + 2.12.0: + changes: + minor_changes: + - api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, + https://github.com/ansible-collections/community.routeros/pull/244). + - api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, + https://github.com/ansible-collections/community.routeros/pull/245). + - api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, + https://github.com/ansible-collections/community.routeros/pull/246). + - api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). + - api_info, api_modify - add support for the ``tx-power`` attribute in ``interface + wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). + - api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` path + (https://github.com/ansible-collections/community.routeros/pull/248). + - api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). + release_summary: Feature release. + fragments: + - 2.12.0.yml + - 226-support-for-WifiWave2.yml + - 239-wireless-tx-power.yml + - 243-add-routing-bgp-template-path.yml + - 244-add-interface-ovpn-client-path.yml + - 245-add-radius-path.yml + - 246-add-routing-rule-path.yml + - 247-removed-primary-key-host-in-tool-netwatch.yml + release_date: '2024-01-21' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.12.0.yml b/changelogs/fragments/2.12.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/2.12.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/226-support-for-WifiWave2.yml b/changelogs/fragments/226-support-for-WifiWave2.yml deleted file mode 100644 index fd98793..0000000 --- a/changelogs/fragments/226-support-for-WifiWave2.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). diff --git a/changelogs/fragments/239-wireless-tx-power.yml b/changelogs/fragments/239-wireless-tx-power.yml deleted file mode 100644 index 560639b..0000000 --- a/changelogs/fragments/239-wireless-tx-power.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``tx-power`` attribute in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). diff --git a/changelogs/fragments/243-add-routing-bgp-template-path.yml b/changelogs/fragments/243-add-routing-bgp-template-path.yml deleted file mode 100644 index c1cf627..0000000 --- a/changelogs/fragments/243-add-routing-bgp-template-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). diff --git a/changelogs/fragments/244-add-interface-ovpn-client-path.yml b/changelogs/fragments/244-add-interface-ovpn-client-path.yml deleted file mode 100644 index 15dbcd9..0000000 --- a/changelogs/fragments/244-add-interface-ovpn-client-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, https://github.com/ansible-collections/community.routeros/pull/244). diff --git a/changelogs/fragments/245-add-radius-path.yml b/changelogs/fragments/245-add-radius-path.yml deleted file mode 100644 index 47572fd..0000000 --- a/changelogs/fragments/245-add-radius-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, https://github.com/ansible-collections/community.routeros/pull/245). diff --git a/changelogs/fragments/246-add-routing-rule-path.yml b/changelogs/fragments/246-add-routing-rule-path.yml deleted file mode 100644 index 53c6263..0000000 --- a/changelogs/fragments/246-add-routing-rule-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, https://github.com/ansible-collections/community.routeros/pull/246). diff --git a/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml b/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml deleted file mode 100644 index 7b7e858..0000000 --- a/changelogs/fragments/247-removed-primary-key-host-in-tool-netwatch.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` path (https://github.com/ansible-collections/community.routeros/pull/248). From 542a362ceef3b7e77592a4b5d0c861dbaf4eef3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Thu, 1 Feb 2024 18:48:14 +0100 Subject: [PATCH 204/365] Fixes #256: make path `user group` modifiable and add `comment` attribute (#257) * Fixes #256: make path `user group` modifiable and add `comment` attribute` Add changelog fragment * Update changelogs/fragments/257-make-user_group-modifiable.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/257-make-user_group-modifiable.yml | 2 ++ plugins/module_utils/_api_data.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/257-make-user_group-modifiable.yml diff --git a/changelogs/fragments/257-make-user_group-modifiable.yml b/changelogs/fragments/257-make-user_group-modifiable.yml new file mode 100644 index 0000000..06de81e --- /dev/null +++ b/changelogs/fragments/257-make-user_group-modifiable.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - make path ``user group`` modifiable and add ``comment`` attribute (https://github.com/ansible-collections/community.routeros/issues/256, https://github.com/ansible-collections/community.routeros/pull/257). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5518abd..d2027d6 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4117,10 +4117,10 @@ PATHS = { ), ('user', 'group'): APIData( unversioned=VersionedAPIData( - fixed_entries=True, primary_keys=('name', ), fully_understood=True, fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), 'name': KeyInfo(), 'policy': KeyInfo(), 'skin': KeyInfo(default='default'), From 6f7abfa8bcfde48aad86f60ef3b6ccfc63ee8659 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Feb 2024 11:41:40 +0100 Subject: [PATCH 205/365] Add MarkDown changelog. (#261) --- CHANGELOG.md | 589 +++++++++++++++++++++++++++++++++++++++++ CHANGELOG.md.license | 3 + CHANGELOG.rst | 4 - README.md | 2 +- changelogs/config.yaml | 3 + 5 files changed, 596 insertions(+), 5 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 CHANGELOG.md.license diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..68f3fcd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,589 @@ +# Community RouterOS Release Notes + +**Topics** +- v2\.12\.0 + - Release Summary + - Minor Changes +- v2\.11\.0 + - Release Summary + - Minor Changes +- v2\.10\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary + - Known Issues +- v2\.8\.2 + - Release Summary + - Bugfixes +- v2\.8\.1 + - Release Summary + - Bugfixes +- v2\.8\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.7\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.6\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.5\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes + - Bugfixes + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary + - Bugfixes +- v2\.2\.0 + - Release Summary + - Minor Changes + - Bugfixes + - New Modules +- v2\.1\.0 + - Release Summary + - Minor Changes + - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes + - New Plugins + - Filter +- v1\.2\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary + - Bugfixes +- v1\.0\.0 + - Release Summary + - Bugfixes +- v0\.1\.1 + - Release Summary + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes + + +## v2\.12\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + +* api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. +* api\_info\, api\_modify \- add radius path \([https\://github\.com/ansible\-collections/community\.routeros/issues/241](https\://github\.com/ansible\-collections/community\.routeros/issues/241)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/245](https\://github\.com/ansible\-collections/community\.routeros/pull/245)\)\. +* api\_info\, api\_modify \- add routing rule path \([https\://github\.com/ansible\-collections/community\.routeros/issues/162](https\://github\.com/ansible\-collections/community\.routeros/issues/162)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/246](https\://github\.com/ansible\-collections/community\.routeros/pull/246)\)\. +* api\_info\, api\_modify \- add missing path routing bgp template \([https\://github\.com/ansible\-collections/community\.routeros/pull/243](https\://github\.com/ansible\-collections/community\.routeros/pull/243)\)\. +* api\_info\, api\_modify \- add support for the tx\-power attribute in interface wireless \([https\://github\.com/ansible\-collections/community\.routeros/pull/239](https\://github\.com/ansible\-collections/community\.routeros/pull/239)\)\. +* api\_info\, api\_modify \- removed host primary key in tool netwatch path \([https\://github\.com/ansible\-collections/community\.routeros/pull/248](https\://github\.com/ansible\-collections/community\.routeros/pull/248)\)\. +* api\_modify\, api\_info \- added support for interface wifiwave2 \([https\://github\.com/ansible\-collections/community\.routeros/pull/226](https\://github\.com/ansible\-collections/community\.routeros/pull/226)\)\. + + +## v2\.11\.0 + + +### Release Summary + +Feature and bugfix release\. + + +### Minor Changes + +* api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) +* api\_info\, api\_modify \- add missing parameters address\-list\, address\-list\-timeout\, randomise\-ports\, and realm to subpaths of the ip firewall path \([https\://github\.com/ansible\-collections/community\.routeros/issues/236](https\://github\.com/ansible\-collections/community\.routeros/issues/236)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/237](https\://github\.com/ansible\-collections/community\.routeros/pull/237)\)\. +* api\_info\, api\_modify \- mark the interface wireless parameter running as read\-only \([https\://github\.com/ansible\-collections/community\.routeros/pull/233](https\://github\.com/ansible\-collections/community\.routeros/pull/233)\)\. +* api\_info\, api\_modify \- set the default value to false for the disabled parameter in some more paths where it can be seen in the documentation \([https\://github\.com/ansible\-collections/community\.routeros/pull/237](https\://github\.com/ansible\-collections/community\.routeros/pull/237)\)\. +* api\_modify \- add missing comment attribute to /routing id \([https\://github\.com/ansible\-collections/community\.routeros/pull/234](https\://github\.com/ansible\-collections/community\.routeros/pull/234)\)\. +* api\_modify \- add missing attributes to the routing bgp connection path \([https\://github\.com/ansible\-collections/community\.routeros/pull/234](https\://github\.com/ansible\-collections/community\.routeros/pull/234)\)\. +* api\_modify \- add versioning to the /tool e\-mail path \(RouterOS 7\.12 release\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/234](https\://github\.com/ansible\-collections/community\.routeros/pull/234)\)\. +* api\_modify \- make /ip traffic\-flow target a multiple value attribute \([https\://github\.com/ansible\-collections/community\.routeros/pull/234](https\://github\.com/ansible\-collections/community\.routeros/pull/234)\)\. + + +## v2\.10\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. +* api\_info\, api\_modify \- add support for address\-list and match\-subdomain introduced by RouterOS 7\.7 in the ip dns static path \([https\://github\.com/ansible\-collections/community\.routeros/pull/197](https\://github\.com/ansible\-collections/community\.routeros/pull/197)\)\. +* api\_info\, api\_modify \- add support for user\, time and gmt\-offset under the system clock path \([https\://github\.com/ansible\-collections/community\.routeros/pull/210](https\://github\.com/ansible\-collections/community\.routeros/pull/210)\)\. +* api\_info\, api\_modify \- add support for the interface ppp\-client path \([https\://github\.com/ansible\-collections/community\.routeros/pull/199](https\://github\.com/ansible\-collections/community\.routeros/pull/199)\)\. +* api\_info\, api\_modify \- add support for the interface wireless path \([https\://github\.com/ansible\-collections/community\.routeros/pull/195](https\://github\.com/ansible\-collections/community\.routeros/pull/195)\)\. +* api\_info\, api\_modify \- add support for the iot modbus path \([https\://github\.com/ansible\-collections/community\.routeros/pull/205](https\://github\.com/ansible\-collections/community\.routeros/pull/205)\)\. +* api\_info\, api\_modify \- add support for the ip dhcp\-server option and ip dhcp\-server option sets paths \([https\://github\.com/ansible\-collections/community\.routeros/pull/223](https\://github\.com/ansible\-collections/community\.routeros/pull/223)\)\. +* api\_info\, api\_modify \- add support for the ip upnp interfaces\, tool graphing interface\, tool graphing resource paths \([https\://github\.com/ansible\-collections/community\.routeros/pull/227](https\://github\.com/ansible\-collections/community\.routeros/pull/227)\)\. +* api\_info\, api\_modify \- add support for the ipv6 firewall nat path \([https\://github\.com/ansible\-collections/community\.routeros/pull/204](https\://github\.com/ansible\-collections/community\.routeros/pull/204)\)\. +* api\_info\, api\_modify \- add support for the mode property in ip neighbor discovery\-settings introduced in RouterOS 7\.7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/198](https\://github\.com/ansible\-collections/community\.routeros/pull/198)\)\. +* api\_info\, api\_modify \- add support for the port remote\-access path \([https\://github\.com/ansible\-collections/community\.routeros/pull/224](https\://github\.com/ansible\-collections/community\.routeros/pull/224)\)\. +* api\_info\, api\_modify \- add support for the routing filter rule and routing filter select\-rule paths \([https\://github\.com/ansible\-collections/community\.routeros/pull/200](https\://github\.com/ansible\-collections/community\.routeros/pull/200)\)\. +* api\_info\, api\_modify \- add support for the routing table path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/215](https\://github\.com/ansible\-collections/community\.routeros/pull/215)\)\. +* api\_info\, api\_modify \- add support for the tool netwatch path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/216](https\://github\.com/ansible\-collections/community\.routeros/pull/216)\)\. +* api\_info\, api\_modify \- add support for the user settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/201](https\://github\.com/ansible\-collections/community\.routeros/pull/201)\)\. +* api\_info\, api\_modify \- add support for the user path \([https\://github\.com/ansible\-collections/community\.routeros/pull/211](https\://github\.com/ansible\-collections/community\.routeros/pull/211)\)\. +* api\_info\, api\_modify \- finalize fields for the interface wireless security\-profiles path and enable it \([https\://github\.com/ansible\-collections/community\.routeros/pull/203](https\://github\.com/ansible\-collections/community\.routeros/pull/203)\)\. +* api\_info\, api\_modify \- finalize fields for the ppp profile path and enable it \([https\://github\.com/ansible\-collections/community\.routeros/pull/217](https\://github\.com/ansible\-collections/community\.routeros/pull/217)\)\. +* api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. +* api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. + + +### Bugfixes + +* api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. + + +## v2\.9\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. +* api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. + + +### Bugfixes + +* api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. + + +## v2\.8\.3 + + +### Release Summary + +Maintenance release with updated documentation\. + +From this version on\, community\.routeros is using the new [Ansible semantic markup](https\://docs\.ansible\.com/ansible/devel/dev\_guide/developing\_modules\_documenting\.html\#semantic\-markup\-within\-module\-documentation) +in its documentation\. If you look at documentation with the ansible\-doc CLI tool +from ansible\-core before 2\.15\, please note that it does not render the markup +correctly\. You should be still able to read it in most cases\, but you need +ansible\-core 2\.15 or later to see it as it is intended\. Alternatively you can +look at [the devel docsite](https\://docs\.ansible\.com/ansible/devel/collections/community/routeros/) +for the rendered HTML version of the documentation of the latest release\. + + +### Known Issues + +* Ansible markup will show up in raw form on ansible\-doc text output for ansible\-core before 2\.15\. If you have trouble deciphering the documentation markup\, please upgrade to ansible\-core 2\.15 \(or newer\)\, or read the HTML documentation on [https\://docs\.ansible\.com/ansible/devel/collections/community/routeros/](https\://docs\.ansible\.com/ansible/devel/collections/community/routeros/)\. + + +## v2\.8\.2 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. + + +## v2\.8\.1 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. + + +## v2\.8\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. + + +### Bugfixes + +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + +* api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +## v2\.6\.0 + + +### Release Summary + +Regular bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. +* api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. + + +### Bugfixes + +* api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. +* api\_modify\, api\_info \- do not crash if router contains regexp DNS entries in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. + + +## v2\.5\.0 + + +### Release Summary + +Feature and bugfix release\. + + +### Minor Changes + +* api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. + + +### Bugfixes + +* api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. + + +## v2\.4\.0 + + +### Release Summary + +Feature release improving the api\* modules\. + + +### Minor Changes + +* api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. +* api\_info \- new parameter include\_builtin which allows to include \"builtin\" entries that are automatically generated by ROS and cannot be modified by the user \([https\://github\.com/ansible\-collections/community\.routeros/pull/130](https\://github\.com/ansible\-collections/community\.routeros/pull/130)\)\. +* api\_modify\, api\_info \- support API paths \- interface bonding\, interface bridge mlag\, ipv6 firewall mangle\, ipv6 nd\, system scheduler\, system script\, system ups \([https\://github\.com/ansible\-collections/community\.routeros/pull/133](https\://github\.com/ansible\-collections/community\.routeros/pull/133)\)\. +* api\_modify\, api\_info \- support API paths caps\-man access\-list\, caps\-man configuration\, caps\-man datapath\, caps\-man manager\, caps\-man provisioning\, caps\-man security \([https\://github\.com/ansible\-collections/community\.routeros/pull/126](https\://github\.com/ansible\-collections/community\.routeros/pull/126)\)\. +* api\_modify\, api\_info \- support API paths interface list and interface list member \([https\://github\.com/ansible\-collections/community\.routeros/pull/120](https\://github\.com/ansible\-collections/community\.routeros/pull/120)\)\. +* api\_modify\, api\_info \- support API paths interface pppoe\-client\, interface vlan\, interface bridge\, interface bridge vlan \([https\://github\.com/ansible\-collections/community\.routeros/pull/125](https\://github\.com/ansible\-collections/community\.routeros/pull/125)\)\. +* api\_modify\, api\_info \- support API paths ip ipsec identity\, ip ipsec peer\, ip ipsec policy\, ip ipsec profile\, ip ipsec proposal \([https\://github\.com/ansible\-collections/community\.routeros/pull/129](https\://github\.com/ansible\-collections/community\.routeros/pull/129)\)\. +* api\_modify\, api\_info \- support API paths ip route and ip route vrf \([https\://github\.com/ansible\-collections/community\.routeros/pull/123](https\://github\.com/ansible\-collections/community\.routeros/pull/123)\)\. +* api\_modify\, api\_info \- support API paths ipv6 address\, ipv6 dhcp\-server\, ipv6 dhcp\-server option\, ipv6 route\, queue tree\, routing ospf area\, routing ospf area range\, routing ospf instance\, routing ospf interface\-template\, routing pimsm instance\, routing pimsm interface\-template \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. +* api\_modify\, api\_info \- support API paths system logging\, system logging action \([https\://github\.com/ansible\-collections/community\.routeros/pull/127](https\://github\.com/ansible\-collections/community\.routeros/pull/127)\)\. +* api\_modify\, api\_info \- support field hw\-offload for path ip firewall filter \([https\://github\.com/ansible\-collections/community\.routeros/pull/121](https\://github\.com/ansible\-collections/community\.routeros/pull/121)\)\. +* api\_modify\, api\_info \- support fields address\-list\, address\-list\-timeout\, connection\-bytes\, connection\-limit\, connection\-mark\, connection\-rate\, connection\-type\, content\, disabled\, dscp\, dst\-address\-list\, dst\-address\-type\, dst\-limit\, fragment\, hotspot\, icmp\-options\, in\-bridge\-port\, in\-bridge\-port\-list\, ingress\-priority\, ipsec\-policy\, ipv4\-options\, jump\-target\, layer7\-protocol\, limit\, log\, log\-prefix\, nth\, out\-bridge\-port\, out\-bridge\-port\-list\, packet\-mark\, packet\-size\, per\-connection\-classifier\, port\, priority\, psd\, random\, realm\, routing\-mark\, same\-not\-by\-dst\, src\-address\, src\-address\-list\, src\-address\-type\, src\-mac\-address\, src\-port\, tcp\-mss\, time\, tls\-host\, ttl in ip firewall nat path \([https\://github\.com/ansible\-collections/community\.routeros/pull/133](https\://github\.com/ansible\-collections/community\.routeros/pull/133)\)\. +* api\_modify\, api\_info \- support fields combo\-mode\, comment\, fec\-mode\, mdix\-enable\, poe\-out\, poe\-priority\, poe\-voltage\, power\-cycle\-interval\, power\-cycle\-ping\-address\, power\-cycle\-ping\-enabled\, power\-cycle\-ping\-timeout for path interface ethernet \([https\://github\.com/ansible\-collections/community\.routeros/pull/121](https\://github\.com/ansible\-collections/community\.routeros/pull/121)\)\. +* api\_modify\, api\_info \- support fields jump\-target\, reject\-with in ip firewall filter API path\, field comment in ip firwall address\-list API path\, field jump\-target in ip firewall mangle API path\, field comment in ipv6 firewall address\-list API path\, fields jump\-target\, reject\-with in ipv6 firewall filter API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/133](https\://github\.com/ansible\-collections/community\.routeros/pull/133)\)\. +* api\_modify\, api\_info \- support for API fields that can be disabled and have default value at the same time\, support API paths interface gre\, interface eoip \([https\://github\.com/ansible\-collections/community\.routeros/pull/128](https\://github\.com/ansible\-collections/community\.routeros/pull/128)\)\. +* api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. +* api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. + + +### Bugfixes + +* api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. +* api\_modify \- queue interface path works now \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. +* api\_modify\, api\_info \- removed wrong field dynamic from API path ipv6 firewall address\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/133](https\://github\.com/ansible\-collections/community\.routeros/pull/133)\)\. +* api\_modify\, api\_info \- the default of the field ingress\-filtering in interface bridge port is now true\, which is the default in ROS \([https\://github\.com/ansible\-collections/community\.routeros/pull/125](https\://github\.com/ansible\-collections/community\.routeros/pull/125)\)\. +* command\, facts \- commands do not timeout in safe mode anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/134](https\://github\.com/ansible\-collections/community\.routeros/pull/134)\)\. + + +### Known Issues + +* api\_modify \- when limits for entries in queue tree are defined as human readable \- for example 25M \-\, the configuration will be correctly set in ROS\, but the module will indicate the item is changed on every run even when there was no change done\. This is caused by the ROS API which returns the number in bytes \- for example 25000000 \(which is inconsistent with the CLI behavior\)\. In order to mitigate that\, the limits have to be defined in bytes \(those will still appear as human readable in the ROS CLI\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. +* api\_modify\, api\_info \- routing ospf area\, routing ospf area range\, routing ospf instance\, routing ospf interface\-template paths are not fully implemented for ROS6 due to the significant changes between ROS6 and ROS7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. + + +## v2\.3\.1 + + +### Release Summary + +Maintenance release with improved documentation\. + + +### Known Issues + +* The community\.routeros\.command module claims to support check mode\. Since it cannot judge whether the commands executed modify state or not\, this behavior is incorrect\. Since this potentially breaks existing playbooks\, we will not change this behavior until community\.routeros 3\.0\.0\. + + +## v2\.3\.0 + + +### Release Summary + +Feature and bugfix release\. + + +### Minor Changes + +* The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. +* api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. +* api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. + + +### Bugfixes + +* api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. + + +## v2\.2\.1 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + +* api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. +* api\_modify\, api\_info \- make API path ip dhcp\-server network support missing options boot\-file\-name\, dhcp\-option\-set\, dns\-none\, domain\, and next\-server \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/106](https\://github\.com/ansible\-collections/community\.routeros/pull/106)\)\. + + +## v2\.2\.0 + + +### Release Summary + +New feature release\. + + +### Minor Changes + +* All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. + + +### Bugfixes + +* Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. + + +### New Modules + +* api\_info \- Retrieve information from API +* api\_modify \- Modify data at paths with API + + +## v2\.1\.0 + + +### Release Summary + +Feature and bugfix release with new modules\. + + +### Minor Changes + +* Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. +* Prepare collection for inclusion in an Execution Environment by declaring its dependencies \([https\://github\.com/ansible\-collections/community\.routeros/pull/83](https\://github\.com/ansible\-collections/community\.routeros/pull/83)\)\. +* api \- add new option extended query more complex queries against RouterOS API \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. +* api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. +* api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. + + +### Bugfixes + +* query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. +* quoting and unquoting filter plugins\, api module \- handle the escape sequence \\\_ correctly as escaping a space and not an underscore \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. + + +### New Modules + +* api\_facts \- Collect facts from remote devices running MikroTik RouterOS using the API +* api\_find\_and\_modify \- Find and modify information using the API + + +## v2\.0\.0 + + +### Release Summary + +A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. + + +### Minor Changes + +* api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. +* command \- the commands and wait\_for options now convert the list elements to strings \([https\://github\.com/ansible\-collections/community\.routeros/pull/55](https\://github\.com/ansible\-collections/community\.routeros/pull/55)\)\. +* facts \- the gather\_subset option now converts the list elements to strings \([https\://github\.com/ansible\-collections/community\.routeros/pull/55](https\://github\.com/ansible\-collections/community\.routeros/pull/55)\)\. + + +### Breaking Changes / Porting Guide + +* api \- due to a programming error\, the module never failed on errors\. This has now been fixed\. If you are relying on the module not failing in case of idempotent commands \(resulting in errors like failure\: already have such address\)\, you need to adjust your roles/playbooks\. We suggest to use failed\_when to accept failure in specific circumstances\, for example failed\_when\: \"\'failure\: already have \' in result\.msg\[0\]\" \([https\://github\.com/ansible\-collections/community\.routeros/pull/39](https\://github\.com/ansible\-collections/community\.routeros/pull/39)\)\. +* api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. +* command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. + + +### Bugfixes + +* api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. +* api \- when converting result lists to dictionaries\, no longer removes second \= and text following that if present \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. +* routeros cliconf plugin \- adjust function signature that was modified in Ansible after creation of this plugin \([https\://github\.com/ansible\-collections/community\.routeros/pull/43](https\://github\.com/ansible\-collections/community\.routeros/pull/43)\)\. + + +### New Plugins + + +#### Filter + +* join \- Join a list of arguments to a command +* list\_to\_dict \- Convert a list of arguments to a list of dictionary +* quote\_argument \- Quote an argument +* quote\_argument\_value \- Quote an argument value +* split \- Split a command into arguments + + +## v1\.2\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. +* api \- add options validate\_certs \(default value true\)\, validate\_cert\_hostname \(default value false\)\, and ca\_path to control certificate validation \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. +* api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. +* fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. + + +### Bugfixes + +* api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. + + +## v1\.1\.0 + + +### Release Summary + +This release allow dashes in usernames for SSH\-based modules\. + + +### Minor Changes + +* command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. +* facts \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. + + +## v1\.0\.1 + + +### Release Summary + +Maintenance release with a bugfix for api\. + + +### Bugfixes + +* api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. + + +## v1\.0\.0 + + +### Release Summary + +This is the first production \(non\-prerelease\) release of community\.routeros\. + + +### Bugfixes + +* routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. + + +## v0\.1\.1 + + +### Release Summary + +Small improvements and bugfixes over the initial release\. + + +### Bugfixes + +* api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. + + +## v0\.1\.0 + + +### Release Summary + +The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. + + +### Minor Changes + +* facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. +* facts \- set configuration export on to verbose\, for full configuration export \([https\://github\.com/ansible\-collections/community\.network/pull/104](https\://github\.com/ansible\-collections/community\.network/pull/104)\)\. diff --git a/CHANGELOG.md.license b/CHANGELOG.md.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/CHANGELOG.md.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c1932ad..bc39196 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,7 +4,6 @@ Community RouterOS Release Notes .. contents:: Topics - v2.12.0 ======= @@ -117,7 +116,6 @@ ansible-core 2.15 or later to see it as it is intended. Alternatively you can look at `the devel docsite `__ for the rendered HTML version of the documentation of the latest release. - Known Issues ------------ @@ -471,7 +469,6 @@ Release Summary This is the first production (non-prerelease) release of ``community.routeros``. - Bugfixes -------- @@ -498,7 +495,6 @@ Release Summary The ``community.routeros`` continues the work on the Ansible RouterOS modules from their state in ``community.network`` 1.2.0. The changes listed here are thus relative to the modules ``community.network.routeros_*``. - Minor Changes ------------- diff --git a/README.md b/README.md index f7fcfa2..df692d6 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ See [Ansible's dev guide](https://docs.ansible.com/ansible/devel/dev_guide/devel ## Release notes -See the [changelog](https://github.com/ansible-collections/community.routeros/blob/main/CHANGELOG.rst). +See the [changelog](https://github.com/ansible-collections/community.routeros/blob/main/CHANGELOG.md). ## Roadmap diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 70a1f67..86412ba 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -12,6 +12,9 @@ mention_ancestor: true flatmap: true new_plugins_after_name: removed_features notesdir: fragments +output_formats: +- rst +- md prelude_section_name: release_summary prelude_section_title: Release Summary sections: From 10fbc564a7279a9f7af41251c61e7c9eba28b9e1 Mon Sep 17 00:00:00 2001 From: liquorice-head <40302350+liquorice-head@users.noreply.github.com> Date: Sun, 18 Feb 2024 01:49:12 +0400 Subject: [PATCH 206/365] Change ip vrf for router OS v7 (#259) * Update api_info.py * Update api_modify.py * Update _api_data.py * Update _api_data.py * Update _api_data.py * Update api_info.py * Update api_modify.py * Update api_info.py * Update api_modify.py * Create 259-add-routeros7-support-for-ip-vrf.yml * Update changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- .../259-add-routeros7-support-for-ip-vrf.yml | 2 ++ plugins/module_utils/_api_data.py | 36 +++++++++++++------ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml diff --git a/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml b/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml new file mode 100644 index 0000000..f55a706 --- /dev/null +++ b/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d2027d6..8353614 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -727,17 +727,33 @@ PATHS = { }, ), ), + ('ip', 'vrf'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interfaces': KeyInfo(), + 'name': KeyInfo(), + }, + )), + ] + ), ('ip', 'route', 'vrf'): APIData( - unversioned=VersionedAPIData( - fully_understood=True, - primary_keys=('routing-mark', ), - fields={ - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'disabled': KeyInfo(default=False), - 'interfaces': KeyInfo(), - 'routing-mark': KeyInfo(), - }, - ), + versioned=[ + ('7', '<', VersionedAPIData( + fully_understood=True, + primary_keys=('routing-mark', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interfaces': KeyInfo(), + 'routing-mark': KeyInfo(), + }, + )), + ], ), ('ip', 'dhcp-server'): APIData( unversioned=VersionedAPIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 6eea5e8..216b2ab 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -147,6 +147,7 @@ options: - ip traffic-flow target - ip upnp - ip upnp interfaces + - ip vrf - ipv6 address - ipv6 dhcp-client - ipv6 dhcp-server diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index a683c2a..d9104bf 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -156,6 +156,7 @@ options: - ip traffic-flow target - ip upnp - ip upnp interfaces + - ip vrf - ipv6 address - ipv6 dhcp-client - ipv6 dhcp-server From 232a013c64dcd97806b0d4a84d43903ecdfb2eca Mon Sep 17 00:00:00 2001 From: Maurizio Pasquinelli Date: Tue, 20 Feb 2024 20:29:41 +0100 Subject: [PATCH 207/365] Fix date removal in nonverbose config (#262) * Fix date removal in nonverbose config As in newer versions of RouterOS the date format is 2024-10-02 and no longer 2024/10/02, the regex did no longer match all cases. This is fixed. * Add changelog fragment --- changelogs/fragments/262-fix-date-removal.yml | 2 ++ plugins/modules/facts.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/262-fix-date-removal.yml diff --git a/changelogs/fragments/262-fix-date-removal.yml b/changelogs/fragments/262-fix-date-removal.yml new file mode 100644 index 0000000..d083a46 --- /dev/null +++ b/changelogs/fragments/262-fix-date-removal.yml @@ -0,0 +1,2 @@ +bugfixes: + - facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index a47e354..50f9a21 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -311,7 +311,7 @@ class Config(FactsBase): '/export', ] - RM_DATE_RE = re.compile(r'^# [a-z0-9/][a-z0-9/]* [0-9:]* by RouterOS') + RM_DATE_RE = re.compile(r'^# [a-z0-9/-][a-z0-9/-]* [0-9:]* by RouterOS') def populate(self): super(Config, self).populate() From afdda50ab09b74dbb0b66fd24363705ee26e4f5c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 23 Feb 2024 20:44:36 +0100 Subject: [PATCH 208/365] Prepare 2.13.0 release. --- changelogs/fragments/2.13.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.13.0.yml diff --git a/changelogs/fragments/2.13.0.yml b/changelogs/fragments/2.13.0.yml new file mode 100644 index 0000000..56de6d9 --- /dev/null +++ b/changelogs/fragments/2.13.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. diff --git a/galaxy.yml b/galaxy.yml index 97d5a33..5e218c3 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.12.0 +version: 2.13.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From f616004caf4032367d5481ae4acdf20da36cb5d9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 25 Feb 2024 20:58:01 +0100 Subject: [PATCH 209/365] Release 2.13.0. --- CHANGELOG.md | 265 ++++++++++-------- CHANGELOG.rst | 19 ++ changelogs/changelog.yaml | 16 ++ changelogs/fragments/2.13.0.yml | 1 - .../257-make-user_group-modifiable.yml | 2 - .../259-add-routeros7-support-for-ip-vrf.yml | 2 - changelogs/fragments/262-fix-date-removal.yml | 2 - 7 files changed, 179 insertions(+), 128 deletions(-) delete mode 100644 changelogs/fragments/2.13.0.yml delete mode 100644 changelogs/fragments/257-make-user_group-modifiable.yml delete mode 100644 changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml delete mode 100644 changelogs/fragments/262-fix-date-removal.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 68f3fcd..393e521 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,108 +1,131 @@ # Community RouterOS Release Notes **Topics** -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - Minor Changes - Bugfixes - - Known Issues -- v2\.3\.1 +- v2\.4\.0 - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - Minor Changes - Bugfixes -- v2\.2\.1 + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary - Bugfixes - - New Modules -- v2\.1\.0 +- v2\.2\.0 - Release Summary - Minor Changes - Bugfixes - - New Modules -- v2\.0\.0 + - New Modules +- v2\.1\.0 - Release Summary - Minor Changes - - Breaking Changes / Porting Guide - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 - - Release Summary - Bugfixes -- v1\.0\.0 +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary - - Minor Changes + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes - -## v2\.12\.0 + +## v2\.13\.0 ### Release Summary -Feature release\. +Bugfix and feature release\. ### Minor Changes +* api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. +* api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) + + +### Bugfixes + +* facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. + + +## v2\.12\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. * api\_info\, api\_modify \- add radius path \([https\://github\.com/ansible\-collections/community\.routeros/issues/241](https\://github\.com/ansible\-collections/community\.routeros/issues/241)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/245](https\://github\.com/ansible\-collections/community\.routeros/pull/245)\)\. * api\_info\, api\_modify \- add routing rule path \([https\://github\.com/ansible\-collections/community\.routeros/issues/162](https\://github\.com/ansible\-collections/community\.routeros/issues/162)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/246](https\://github\.com/ansible\-collections/community\.routeros/pull/246)\)\. @@ -114,12 +137,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -134,12 +157,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -163,7 +186,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -171,18 +194,18 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -190,7 +213,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -211,19 +234,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -232,35 +242,23 @@ Bugfix release\. ### Bugfixes -* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - -## v2\.8\.0 + +## v2\.8\.1 ### Release Summary -Bugfix and feature release\. - - -### Minor Changes - -* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. -* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. -* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. -* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. +Bugfix release\. ### Bugfixes -* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. - -## v2\.7\.0 + +## v2\.8\.0 ### Release Summary @@ -270,28 +268,53 @@ Bugfix and feature release\. ### Minor Changes -* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. ### Bugfixes +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -300,17 +323,17 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -318,12 +341,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -344,7 +367,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -362,7 +385,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -375,19 +398,19 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -395,12 +418,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -409,17 +432,17 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -433,12 +456,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -447,7 +470,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -462,12 +485,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -481,7 +504,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -503,12 +526,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -516,7 +539,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -524,12 +547,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -538,12 +561,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -551,12 +574,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -564,12 +587,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -577,12 +600,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bc39196..8205bb5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,25 @@ Community RouterOS Release Notes .. contents:: Topics +v2.13.0 +======= + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_info, api_modify - make path ``user group`` modifiable and add ``comment`` attribute (https://github.com/ansible-collections/community.routeros/issues/256, https://github.com/ansible-collections/community.routeros/pull/257). +- api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) + +Bugfixes +-------- + +- facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). + v2.12.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 6461aa6..03d14b6 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -307,6 +307,22 @@ releases: - 246-add-routing-rule-path.yml - 247-removed-primary-key-host-in-tool-netwatch.yml release_date: '2024-01-21' + 2.13.0: + changes: + bugfixes: + - facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). + minor_changes: + - api_info, api_modify - make path ``user group`` modifiable and add ``comment`` + attribute (https://github.com/ansible-collections/community.routeros/issues/256, + https://github.com/ansible-collections/community.routeros/pull/257). + - api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) + release_summary: Bugfix and feature release. + fragments: + - 2.13.0.yml + - 257-make-user_group-modifiable.yml + - 259-add-routeros7-support-for-ip-vrf.yml + - 262-fix-date-removal.yml + release_date: '2024-02-25' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.13.0.yml b/changelogs/fragments/2.13.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/2.13.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. diff --git a/changelogs/fragments/257-make-user_group-modifiable.yml b/changelogs/fragments/257-make-user_group-modifiable.yml deleted file mode 100644 index 06de81e..0000000 --- a/changelogs/fragments/257-make-user_group-modifiable.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - make path ``user group`` modifiable and add ``comment`` attribute (https://github.com/ansible-collections/community.routeros/issues/256, https://github.com/ansible-collections/community.routeros/pull/257). diff --git a/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml b/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml deleted file mode 100644 index f55a706..0000000 --- a/changelogs/fragments/259-add-routeros7-support-for-ip-vrf.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) diff --git a/changelogs/fragments/262-fix-date-removal.yml b/changelogs/fragments/262-fix-date-removal.yml deleted file mode 100644 index d083a46..0000000 --- a/changelogs/fragments/262-fix-date-removal.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). From ffd5a6370cdcc27370e475bb0d4e28f46f833d1f Mon Sep 17 00:00:00 2001 From: hansmi Date: Sat, 2 Mar 2024 12:49:37 +0100 Subject: [PATCH 210/365] Add missing fields in "system package update" (#263) Signed-off-by: Michael Hanselmann --- changelogs/fragments/263-sys-pkg-update.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/263-sys-pkg-update.yml diff --git a/changelogs/fragments/263-sys-pkg-update.yml b/changelogs/fragments/263-sys-pkg-update.yml new file mode 100644 index 0000000..9d3c3d1 --- /dev/null +++ b/changelogs/fragments/263-sys-pkg-update.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 8353614..dfbaa23 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3508,6 +3508,9 @@ PATHS = { fully_understood=True, fields={ 'channel': KeyInfo(default='stable'), + 'installed-version': KeyInfo(read_only=True), + 'latest-version': KeyInfo(read_only=True), + 'status': KeyInfo(read_only=True), }, ), ), From 84009262d0e684df581536607ef92d7da6035208 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 3 Mar 2024 08:32:41 +0100 Subject: [PATCH 211/365] Remove default value for "running" field in "interface wireless" (#264) The `running` field can't be configured. By having a default value it's written and shows up in diffs. --- changelogs/fragments/264-wireless-running-default.yml | 2 ++ plugins/module_utils/_api_data.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/264-wireless-running-default.yml diff --git a/changelogs/fragments/264-wireless-running-default.yml b/changelogs/fragments/264-wireless-running-default.yml new file mode 100644 index 0000000..5341718 --- /dev/null +++ b/changelogs/fragments/264-wireless-running-default.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - remove default value for read-only ``running`` field in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index dfbaa23..03c5833 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1932,7 +1932,7 @@ PATHS = { 'radio-name': KeyInfo(), 'rate-selection': KeyInfo(default='advanced'), 'rate-set': KeyInfo(default='default'), - 'running': KeyInfo(default=False, read_only=True), + 'running': KeyInfo(read_only=True), 'rx-chains': KeyInfo(default='0,1'), 'scan-list': KeyInfo(default='default'), 'secondary-frequency': KeyInfo(default=''), From 2ea1fef535e375011800f005ac028efa9d2d02ba Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 3 Mar 2024 09:03:25 +0100 Subject: [PATCH 212/365] KeyInfo: prevent read_only usage with can_disable, remove_value, absent_value, default, or required (#265) * Prevent read_only usage with can_disable, remove_value, absent_value, default, or required. * Add test. --- plugins/module_utils/_api_data.py | 2 ++ tests/unit/plugins/module_utils/test__api_data.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 03c5833..1fd634e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -199,6 +199,8 @@ class KeyInfo(object): raise ValueError('absent_value can not be combined with default, automatically_computed_from, can_disable=True, or absent_value') if read_only and write_only: raise ValueError('read_only and write_only cannot be used at the same time') + if read_only and any([can_disable, remove_value is not None, absent_value is not None, default is not None, required]): + raise ValueError('read_only can not be combined with can_disable, remove_value, absent_value, default, or required') self.can_disable = can_disable self.remove_value = remove_value self.automatically_computed_from = automatically_computed_from diff --git a/tests/unit/plugins/module_utils/test__api_data.py b/tests/unit/plugins/module_utils/test__api_data.py index 5a346eb..4c0267e 100644 --- a/tests/unit/plugins/module_utils/test__api_data.py +++ b/tests/unit/plugins/module_utils/test__api_data.py @@ -103,6 +103,10 @@ def test_key_info_errors(): KeyInfo(read_only=True, write_only=True) assert exc.value.args[0] == 'read_only and write_only cannot be used at the same time' + with pytest.raises(ValueError) as exc: + KeyInfo(read_only=True, default=0) + assert exc.value.args[0] == 'read_only can not be combined with can_disable, remove_value, absent_value, default, or required' + SPLIT_PATHS = [ ('', [], ''), From 3d737d679d6ce99888fb9085720a3f935903a118 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 07:12:46 +0100 Subject: [PATCH 213/365] Bump fsfe/reuse-action from 2 to 3 (#267) Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 2 to 3. - [Release notes](https://github.com/fsfe/reuse-action/releases) - [Commits](https://github.com/fsfe/reuse-action/compare/v2...v3) --- updated-dependencies: - dependency-name: fsfe/reuse-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/reuse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index bde03ff..b6732cc 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -24,4 +24,4 @@ jobs: - uses: actions/checkout@v4 - name: REUSE Compliance Check - uses: fsfe/reuse-action@v2 + uses: fsfe/reuse-action@v3 From d8ae2f41d20c9ee8b09560e4b14fff4a666d92c8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 23 Mar 2024 12:28:34 +0100 Subject: [PATCH 214/365] Ignore pylint warnings for construct that does not work with Python 2 (#268) * Ignore pylint warnings for construct that does not work with Python 2. * Revert "Ignore pylint warnings for construct that does not work with Python 2." This reverts commit 407b2ef93addee8cebc5ef0aca88ebb8525a8805. * Different approach: use ignore.txt since otherwise ansible-core 2.14 tests fail. --- tests/sanity/ignore-2.17.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt index ce635c3..0a5234b 100644 --- a/tests/sanity/ignore-2.17.txt +++ b/tests/sanity/ignore-2.17.txt @@ -1 +1,2 @@ update-docs.py shebang +tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 From 10a419465a4e5a0ba64f60098189a642101f05ce Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 24 Mar 2024 22:16:24 +0100 Subject: [PATCH 215/365] Prepare 2.14.0 release. --- changelogs/fragments/2.14.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.14.0.yml diff --git a/changelogs/fragments/2.14.0.yml b/changelogs/fragments/2.14.0.yml new file mode 100644 index 0000000..63e0654 --- /dev/null +++ b/changelogs/fragments/2.14.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 5e218c3..0ddaab4 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.13.0 +version: 2.14.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From edcd760dbf4902cb34df4267af8864e194f9a227 Mon Sep 17 00:00:00 2001 From: Andrei Costescu Date: Mon, 25 Mar 2024 13:57:24 +0100 Subject: [PATCH 216/365] Add interface wifi paths (#266) * Add interface wifi paths * Update changelog * Remove most defaults --- changelogs/fragments/266-interface-wifi.yml | 2 + plugins/module_utils/_api_data.py | 389 ++++++++++++++++++++ plugins/modules/api_info.py | 12 + plugins/modules/api_modify.py | 12 + 4 files changed, 415 insertions(+) create mode 100644 changelogs/fragments/266-interface-wifi.yml diff --git a/changelogs/fragments/266-interface-wifi.yml b/changelogs/fragments/266-interface-wifi.yml new file mode 100644 index 0000000..e593e81 --- /dev/null +++ b/changelogs/fragments/266-interface-wifi.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - added support for ``interface wifi`` and its sub-paths (https://github.com/ansible-collections/community.routeros/pull/266). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 1fd634e..a421cff 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1533,6 +1533,395 @@ PATHS = { }, ), ), + ('interface', 'wifi'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + required_one_of=[['default-name', 'radio-mac', 'master-interface']], + fields={ + 'aaa.called-format': KeyInfo(can_disable=True), + 'aaa.calling-format': KeyInfo(can_disable=True), + 'aaa.interim-update': KeyInfo(can_disable=True), + 'aaa.mac-caching': KeyInfo(can_disable=True), + 'aaa.nas-identifier': KeyInfo(can_disable=True), + 'aaa.password-format': KeyInfo(can_disable=True), + 'aaa.username-format': KeyInfo(can_disable=True), + 'aaa': KeyInfo(can_disable=True), + 'arp-timeout': KeyInfo(default='auto'), + 'arp': KeyInfo(can_disable=True), + 'channel.band': KeyInfo(can_disable=True), + 'channel.frequency': KeyInfo(can_disable=True), + 'channel.secondary-frequency': KeyInfo(can_disable=True), + 'channel.skip-dfs-channels': KeyInfo(can_disable=True), + 'channel.width': KeyInfo(can_disable=True), + 'channel': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'configuration.antenna-gain': KeyInfo(can_disable=True), + 'configuration.beacon-interval': KeyInfo(can_disable=True), + 'configuration.chains': KeyInfo(can_disable=True), + 'configuration.country': KeyInfo(can_disable=True), + 'configuration.dtim-period': KeyInfo(can_disable=True), + 'configuration.hide-ssid': KeyInfo(can_disable=True), + 'configuration.manager': KeyInfo(can_disable=True), + 'configuration.mode': KeyInfo(can_disable=True), + 'configuration.multicast-enhance': KeyInfo(can_disable=True), + 'configuration.qos-classifier': KeyInfo(can_disable=True), + 'configuration.ssid': KeyInfo(can_disable=True), + 'configuration.tx-chain': KeyInfo(can_disable=True), + 'configuration.tx-power': KeyInfo(can_disable=True), + 'configuration': KeyInfo(can_disable=True), + 'datapath.bridge-cost': KeyInfo(can_disable=True), + 'datapath.bridge-horizon': KeyInfo(can_disable=True), + 'datapath.bridge': KeyInfo(can_disable=True), + 'datapath.client-isolation': KeyInfo(can_disable=True), + 'datapath.interface-list': KeyInfo(can_disable=True), + 'datapath.vlan-id': KeyInfo(can_disable=True), + 'datapath': KeyInfo(can_disable=True), + 'default-name': KeyInfo(), + 'disable-running-check': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=True), + 'interworking.3gpp-info': KeyInfo(can_disable=True), + 'interworking.authentication-types': KeyInfo(can_disable=True), + 'interworking.connection-capabilities': KeyInfo(can_disable=True), + 'interworking.domain-names': KeyInfo(can_disable=True), + 'interworking.esr': KeyInfo(can_disable=True), + 'interworking.hessid': KeyInfo(can_disable=True), + 'interworking.hotspot20-dgaf': KeyInfo(can_disable=True), + 'interworking.hotspot20': KeyInfo(can_disable=True), + 'interworking.internet': KeyInfo(can_disable=True), + 'interworking.ipv4-availability': KeyInfo(can_disable=True), + 'interworking.ipv6-availability': KeyInfo(can_disable=True), + 'interworking.network-type': KeyInfo(can_disable=True), + 'interworking.operational-classes': KeyInfo(can_disable=True), + 'interworking.operator-names': KeyInfo(can_disable=True), + 'interworking.realms': KeyInfo(can_disable=True), + 'interworking.roaming-ois': KeyInfo(can_disable=True), + 'interworking.uesa': KeyInfo(can_disable=True), + 'interworking.venue-names': KeyInfo(can_disable=True), + 'interworking.venue': KeyInfo(can_disable=True), + 'interworking.wan-at-capacity': KeyInfo(can_disable=True), + 'interworking.wan-downlink-load': KeyInfo(can_disable=True), + 'interworking.wan-downlink': KeyInfo(can_disable=True), + 'interworking.wan-measurement-duration': KeyInfo(can_disable=True), + 'interworking.wan-status': KeyInfo(can_disable=True), + 'interworking.wan-symmetric': KeyInfo(can_disable=True), + 'interworking.wan-uplink-load': KeyInfo(can_disable=True), + 'interworking.wan-uplink': KeyInfo(can_disable=True), + 'interworking': KeyInfo(can_disable=True), + 'l2mtu': KeyInfo(default=1560), + 'mac-address': KeyInfo(), + 'master-interface': KeyInfo(), + 'mtu': KeyInfo(default=1500), + 'name': KeyInfo(), + 'radio-mac': KeyInfo(), + 'security.authentication-types': KeyInfo(can_disable=True), + 'security.connect-group': KeyInfo(can_disable=True), + 'security.connect-priority': KeyInfo(can_disable=True), + 'security.dh-groups': KeyInfo(can_disable=True), + 'security.disable-pmkid': KeyInfo(can_disable=True), + 'security.eap-accounting': KeyInfo(can_disable=True), + 'security.eap-anonymous-identity': KeyInfo(can_disable=True), + 'security.eap-certificate-mode': KeyInfo(can_disable=True), + 'security.eap-methods': KeyInfo(can_disable=True), + 'security.eap-password': KeyInfo(can_disable=True), + 'security.eap-tls-certificate': KeyInfo(can_disable=True), + 'security.eap-username': KeyInfo(can_disable=True), + 'security.encryption': KeyInfo(can_disable=True), + 'security.ft-mobility-domain': KeyInfo(can_disable=True), + 'security.ft-nas-identifier': KeyInfo(can_disable=True), + 'security.ft-over-ds': KeyInfo(can_disable=True), + 'security.ft-preserve-vlanid': KeyInfo(can_disable=True), + 'security.ft-r0-key-lifetime': KeyInfo(can_disable=True), + 'security.ft-reassociation-deadline': KeyInfo(can_disable=True), + 'security.ft': KeyInfo(can_disable=True), + 'security.group-encryption': KeyInfo(can_disable=True), + 'security.group-key-update': KeyInfo(can_disable=True), + 'security.management-encryption': KeyInfo(can_disable=True), + 'security.management-protection': KeyInfo(can_disable=True), + 'security.owe-transition-interface': KeyInfo(can_disable=True), + 'security.passphrase': KeyInfo(can_disable=True), + 'security.sae-anti-clogging-threshold': KeyInfo(can_disable=True), + 'security.sae-max-failure-rate': KeyInfo(can_disable=True), + 'security.sae-pwe': KeyInfo(can_disable=True), + 'security.wps': KeyInfo(can_disable=True), + 'security': KeyInfo(can_disable=True), + 'steering.neighbor-group': KeyInfo(can_disable=True), + 'steering.rrm': KeyInfo(can_disable=True), + 'steering.wnm': KeyInfo(can_disable=True), + 'steering': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'aaa'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'called-format': KeyInfo(can_disable=True), + 'calling-format': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interim-update': KeyInfo(can_disable=True), + 'mac-caching': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'nas-identifier': KeyInfo(can_disable=True), + 'password-format': KeyInfo(can_disable=True), + 'username-format': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'access-list'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='accept'), + 'allow-signal-out-of-range': KeyInfo(can_disable=True), + 'client-isolation': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(can_disable=True), + 'mac-address-mask': KeyInfo(can_disable=True), + 'mac-address': KeyInfo(can_disable=True), + 'passphrase': KeyInfo(can_disable=True), + 'radius-accounting': KeyInfo(can_disable=True), + 'signal-range': KeyInfo(can_disable=True), + 'ssid-regexp': KeyInfo(can_disable=True), + 'time': KeyInfo(can_disable=True), + 'vlan-id': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'cap'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'caps-man-addresses': KeyInfo(default=''), + 'caps-man-certificate-common-names': KeyInfo(default=''), + 'caps-man-names': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'discovery-interfaces': KeyInfo(default=''), + 'enabled': KeyInfo(default=False), + 'lock-to-caps-man': KeyInfo(default=False), + 'slaves-datapath': KeyInfo(), + 'slaves-static': KeyInfo(), + }, + )), + ], + ), + ('interface', 'wifi', 'capsman'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'ca-certificate': KeyInfo(default=''), + 'certificate': KeyInfo(default='none'), + 'enabled': KeyInfo(default=False), + 'interfaces': KeyInfo(default=''), + 'package-path': KeyInfo(default=''), + 'require-peer-certificate': KeyInfo(default=False), + 'upgrade-policy': KeyInfo(default='none'), + }, + )), + ], + ), + ('interface', 'wifi', 'channel'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'band': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'frequency': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'secondary-frequency': KeyInfo(can_disable=True), + 'skip-dfs-channels': KeyInfo(can_disable=True), + 'width': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'configuration'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'aaa': KeyInfo(can_disable=True), + 'antenna-gain': KeyInfo(can_disable=True), + 'beacon-interval': KeyInfo(can_disable=True), + 'chains': KeyInfo(can_disable=True), + 'channel': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'country': KeyInfo(can_disable=True), + 'datapath': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'dtim-period': KeyInfo(can_disable=True), + 'hide-ssid': KeyInfo(default=False), + 'interworking': KeyInfo(can_disable=True), + 'manager': KeyInfo(can_disable=True), + 'mode': KeyInfo(can_disable=True), + 'multicast-enhance': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'qos-classifier': KeyInfo(can_disable=True), + 'security': KeyInfo(can_disable=True), + 'ssid': KeyInfo(can_disable=True), + 'steering': KeyInfo(can_disable=True), + 'tx-chains': KeyInfo(can_disable=True), + 'tx-power': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'datapath'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'bridge-cost': KeyInfo(can_disable=True), + 'bridge-horizon': KeyInfo(can_disable=True), + 'bridge': KeyInfo(can_disable=True), + 'client-isolation': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface-list': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'vlan-id': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'interworking'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + '3gpp-info': KeyInfo(can_disable=True), + 'authentication-types': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connection-capabilities': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'domain-names': KeyInfo(can_disable=True), + 'esr': KeyInfo(can_disable=True), + 'hessid': KeyInfo(can_disable=True), + 'hotspot20-dgaf': KeyInfo(can_disable=True), + 'hotspot20': KeyInfo(can_disable=True), + 'internet': KeyInfo(can_disable=True), + 'ipv4-availability': KeyInfo(can_disable=True), + 'ipv6-availability': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'network-type': KeyInfo(can_disable=True), + 'operational-classes': KeyInfo(can_disable=True), + 'operator-names': KeyInfo(can_disable=True), + 'realms': KeyInfo(can_disable=True), + 'roaming-ois': KeyInfo(can_disable=True), + 'uesa': KeyInfo(can_disable=True), + 'venue-names': KeyInfo(can_disable=True), + 'venue': KeyInfo(can_disable=True), + 'wan-at-capacity': KeyInfo(can_disable=True), + 'wan-downlink-load': KeyInfo(can_disable=True), + 'wan-downlink': KeyInfo(can_disable=True), + 'wan-measurement-duration': KeyInfo(can_disable=True), + 'wan-status': KeyInfo(can_disable=True), + 'wan-symmetric': KeyInfo(can_disable=True), + 'wan-uplink-load': KeyInfo(can_disable=True), + 'wan-uplink': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'provisioning'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('action', ), + fields={ + 'action': KeyInfo(default='none'), + 'address-ranges': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'common-name-regexp': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'identity-regexp': KeyInfo(can_disable=True), + 'master-configuration': KeyInfo(can_disable=True), + 'name-format': KeyInfo(can_disable=True), + 'radio-mac': KeyInfo(can_disable=True), + 'slave-configurations': KeyInfo(can_disable=True), + 'supported-bands': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'security'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'authentication-types': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connect-group': KeyInfo(can_disable=True), + 'connect-priority': KeyInfo(can_disable=True), + 'dh-groups': KeyInfo(can_disable=True), + 'disable-pmkid': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'eap-accounting': KeyInfo(can_disable=True), + 'eap-anonymous-identity': KeyInfo(can_disable=True), + 'eap-certificate-mode': KeyInfo(can_disable=True), + 'eap-methods': KeyInfo(can_disable=True), + 'eap-password': KeyInfo(can_disable=True), + 'eap-tls-certificate': KeyInfo(can_disable=True), + 'eap-username': KeyInfo(can_disable=True), + 'encryption': KeyInfo(can_disable=True), + 'ft-mobility-domain': KeyInfo(can_disable=True), + 'ft-nas-identifier': KeyInfo(can_disable=True), + 'ft-over-ds': KeyInfo(can_disable=True), + 'ft-preserve-vlanid': KeyInfo(can_disable=True), + 'ft-r0-key-lifetime': KeyInfo(can_disable=True), + 'ft-reassociation-deadline': KeyInfo(can_disable=True), + 'ft': KeyInfo(can_disable=True), + 'group-encryption': KeyInfo(can_disable=True), + 'group-key-update': KeyInfo(can_disable=True), + 'management-encryption': KeyInfo(can_disable=True), + 'management-protection': KeyInfo(can_disable=True), + 'name': KeyInfo(), + 'owe-transition-interface': KeyInfo(can_disable=True), + 'passphrase': KeyInfo(can_disable=True), + 'sae-anti-clogging-threshold': KeyInfo(can_disable=True), + 'sae-max-failure-rate': KeyInfo(can_disable=True), + 'sae-pwe': KeyInfo(can_disable=True), + 'wps': KeyInfo(can_disable=True), + }, + )), + ], + ), + ('interface', 'wifi', 'steering'): APIData( + versioned=[ + ('7.13', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'neighbor-group': KeyInfo(can_disable=True), + 'rrm': KeyInfo(can_disable=True), + 'wnm': KeyInfo(can_disable=True), + }, + )), + ], + ), ('interface', 'wifiwave2'): APIData( versioned=[ ('7.13', '>=', 'RouterOS 7.13 uses WiFi package'), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 216b2ab..f9a3946 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -79,6 +79,18 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wifi + - interface wifi aaa + - interface wifi access-list + - interface wifi cap + - interface wifi capsman + - interface wifi channel + - interface wifi configuration + - interface wifi datapath + - interface wifi interworking + - interface wifi provisioning + - interface wifi security + - interface wifi steering - interface wifiwave2 - interface wifiwave2 aaa - interface wifiwave2 access-list diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d9104bf..d717500 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -88,6 +88,18 @@ options: - interface sstp-server server - interface vlan - interface vrrp + - interface wifi + - interface wifi aaa + - interface wifi access-list + - interface wifi cap + - interface wifi capsman + - interface wifi channel + - interface wifi configuration + - interface wifi datapath + - interface wifi interworking + - interface wifi provisioning + - interface wifi security + - interface wifi steering - interface wifiwave2 - interface wifiwave2 aaa - interface wifiwave2 access-list From a3fbe88f2f2c03cfe6031e3362f4aaa661d34aaa Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 25 Mar 2024 14:04:48 +0100 Subject: [PATCH 217/365] Release 2.14.0. --- CHANGELOG.md | 293 ++++++++++-------- CHANGELOG.rst | 15 + changelogs/changelog.yaml | 16 + changelogs/fragments/2.14.0.yml | 1 - changelogs/fragments/263-sys-pkg-update.yml | 2 - .../264-wireless-running-default.yml | 2 - changelogs/fragments/266-interface-wifi.yml | 2 - 7 files changed, 187 insertions(+), 144 deletions(-) delete mode 100644 changelogs/fragments/2.14.0.yml delete mode 100644 changelogs/fragments/263-sys-pkg-update.yml delete mode 100644 changelogs/fragments/264-wireless-running-default.yml delete mode 100644 changelogs/fragments/266-interface-wifi.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 393e521..99d0bbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,112 +1,131 @@ # Community RouterOS Release Notes **Topics** -- v2\.13\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.12\.0 - - Release Summary - - Minor Changes -- v2\.11\.0 - - Release Summary - - Minor Changes -- v2\.10\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.9\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.8\.3 - - Release Summary - - Known Issues -- v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - - Release Summary - - Bugfixes -- v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.6\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.5\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.4\.0 - - Release Summary - - Minor Changes - - Bugfixes - - Known Issues -- v2\.3\.1 - - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.2\.1 - - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes - - New Modules -- v2\.1\.0 - - Release Summary - - Minor Changes - - Bugfixes - - New Modules -- v2\.0\.0 - - Release Summary - - Minor Changes - - Breaking Changes / Porting Guide - - Bugfixes - - New Plugins - - Filter -- v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - - Release Summary - - Minor Changes -- v1\.0\.1 - - Release Summary - - Bugfixes -- v1\.0\.0 - - Release Summary - - Bugfixes -- v0\.1\.1 - - Release Summary - - Bugfixes -- v0\.1\.0 - - Release Summary - - Minor Changes - -## v2\.13\.0 +- v2\.14\.0 + - Release Summary + - Minor Changes +- v2\.13\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.12\.0 + - Release Summary + - Minor Changes +- v2\.11\.0 + - Release Summary + - Minor Changes +- v2\.10\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary + - Known Issues +- v2\.8\.2 + - Release Summary + - Bugfixes +- v2\.8\.1 + - Release Summary + - Bugfixes +- v2\.8\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.7\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.6\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.5\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes + - Bugfixes + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary + - Bugfixes +- v2\.2\.0 + - Release Summary + - Minor Changes + - Bugfixes + - New Modules +- v2\.1\.0 + - Release Summary + - Minor Changes + - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes + - New Plugins + - Filter +- v1\.2\.0 + - Release Summary + - Minor Changes + - Bugfixes +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary + - Bugfixes +- v1\.0\.0 + - Release Summary + - Bugfixes +- v0\.1\.1 + - Release Summary + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes + + +## v2\.14\.0 ### Release Summary -Bugfix and feature release\. +Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. +* api\_info\, api\_modify \- added support for interface wifi and its sub\-paths \([https\://github\.com/ansible\-collections/community\.routeros/pull/266](https\://github\.com/ansible\-collections/community\.routeros/pull/266)\)\. +* api\_info\, api\_modify \- remove default value for read\-only running field in interface wireless \([https\://github\.com/ansible\-collections/community\.routeros/pull/264](https\://github\.com/ansible\-collections/community\.routeros/pull/264)\)\. + + +## v2\.13\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) @@ -118,12 +137,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -137,12 +156,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -157,12 +176,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -194,12 +213,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -213,7 +232,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -234,7 +253,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -247,7 +266,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -260,12 +279,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -285,12 +304,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -303,12 +322,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -323,12 +342,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -341,12 +360,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -385,7 +404,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -398,12 +417,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -418,7 +437,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -432,12 +451,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -456,12 +475,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -485,12 +504,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -526,12 +545,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -547,12 +566,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -561,7 +580,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -574,7 +593,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -587,7 +606,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -600,12 +619,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8205bb5..c7cc6ef 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,21 @@ Community RouterOS Release Notes .. contents:: Topics +v2.14.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). +- api_info, api_modify - added support for ``interface wifi`` and its sub-paths (https://github.com/ansible-collections/community.routeros/pull/266). +- api_info, api_modify - remove default value for read-only ``running`` field in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). + v2.13.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 03d14b6..e23348b 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -323,6 +323,22 @@ releases: - 259-add-routeros7-support-for-ip-vrf.yml - 262-fix-date-removal.yml release_date: '2024-02-25' + 2.14.0: + changes: + minor_changes: + - api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` + and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). + - api_info, api_modify - added support for ``interface wifi`` and its sub-paths + (https://github.com/ansible-collections/community.routeros/pull/266). + - api_info, api_modify - remove default value for read-only ``running`` field + in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). + release_summary: Feature release. + fragments: + - 2.14.0.yml + - 263-sys-pkg-update.yml + - 264-wireless-running-default.yml + - 266-interface-wifi.yml + release_date: '2024-03-25' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.14.0.yml b/changelogs/fragments/2.14.0.yml deleted file mode 100644 index 63e0654..0000000 --- a/changelogs/fragments/2.14.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. \ No newline at end of file diff --git a/changelogs/fragments/263-sys-pkg-update.yml b/changelogs/fragments/263-sys-pkg-update.yml deleted file mode 100644 index 9d3c3d1..0000000 --- a/changelogs/fragments/263-sys-pkg-update.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). diff --git a/changelogs/fragments/264-wireless-running-default.yml b/changelogs/fragments/264-wireless-running-default.yml deleted file mode 100644 index 5341718..0000000 --- a/changelogs/fragments/264-wireless-running-default.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - remove default value for read-only ``running`` field in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). diff --git a/changelogs/fragments/266-interface-wifi.yml b/changelogs/fragments/266-interface-wifi.yml deleted file mode 100644 index e593e81..0000000 --- a/changelogs/fragments/266-interface-wifi.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - added support for ``interface wifi`` and its sub-paths (https://github.com/ansible-collections/community.routeros/pull/266). From 8351bff0e9793d9c7d6c78ee6cdf64e7667c5de5 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 3 Apr 2024 07:59:10 +0200 Subject: [PATCH 218/365] Add stable-2.17 to CI; copy 2.17 ignore.txt files to 2.18. (#275) --- .github/workflows/ansible-test.yml | 6 ++++++ README.md | 2 +- tests/sanity/ignore-2.18.txt | 2 ++ tests/sanity/ignore-2.18.txt.license | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/sanity/ignore-2.18.txt create mode 100644 tests/sanity/ignore-2.18.txt.license diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 0444f59..f743ae5 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -34,6 +34,7 @@ jobs: - stable-2.14 - stable-2.15 - stable-2.16 + - stable-2.17 - devel # Ansible-test on various stable branches does not yet work well with cgroups v2. # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 @@ -79,6 +80,7 @@ jobs: - stable-2.14 - stable-2.15 - stable-2.16 + - stable-2.17 - devel steps: @@ -113,6 +115,7 @@ jobs: python: - "3.10" - "3.11" + - "3.12" include: # 2.9 - ansible: stable-2.9 @@ -142,6 +145,9 @@ jobs: # 2.16 - ansible: stable-2.16 python: "3.10" + # 2.17 + - ansible: stable-2.17 + python: "3.12" steps: - name: >- diff --git a/README.md b/README.md index df692d6..e617a8f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can find [documentation for the modules and plugins in this collection here] ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, and ansible-core 2.16 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, and ansible-core 2.17 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements diff --git a/tests/sanity/ignore-2.18.txt b/tests/sanity/ignore-2.18.txt new file mode 100644 index 0000000..0a5234b --- /dev/null +++ b/tests/sanity/ignore-2.18.txt @@ -0,0 +1,2 @@ +update-docs.py shebang +tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 diff --git a/tests/sanity/ignore-2.18.txt.license b/tests/sanity/ignore-2.18.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.18.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From 506b3eba392c1d95307c959a69d1624af2c248da Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 06:57:48 +0930 Subject: [PATCH 219/365] Add '/queue simple' path (#269) * Add '/queue simple' path * Add changelogs/fragments/260-add-queue_simple-path.yml * Updated queue-simple path: - Updated all default values to match those from the API - Re-ordered fields to match API output - Target is not required; added default value * 'target' *is* required, however it interracts strangely with values of 0.0.0.0/0 and '' (Empty string). * Updated PR in document fragment --- .../fragments/269-add-queue_simple-path.yml | 2 ++ plugins/module_utils/_api_data.py | 24 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 28 insertions(+) create mode 100644 changelogs/fragments/269-add-queue_simple-path.yml diff --git a/changelogs/fragments/269-add-queue_simple-path.yml b/changelogs/fragments/269-add-queue_simple-path.yml new file mode 100644 index 0000000..f943de5 --- /dev/null +++ b/changelogs/fragments/269-add-queue_simple-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index a421cff..0b06cc5 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4239,6 +4239,30 @@ PATHS = { }, ), ), + ('queue', 'simple'): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dst': KeyInfo(can_disable=True, remove_value=''), + 'time': KeyInfo(can_disable=True, remove_value=''), + 'bucket-size': KeyInfo(default='0.1/0.1'), + 'burst-limit': KeyInfo(default='0/0'), + 'burst-threshold': KeyInfo(default='0/0'), + 'burst-time': KeyInfo(default='0s/0s'), + 'disabled': KeyInfo(default=False), + 'limit-at': KeyInfo(default='0/0'), + 'max-limit': KeyInfo(default='0/0'), + 'name': KeyInfo(), + 'packet-marks': KeyInfo(default=''), + 'parent': KeyInfo(default='none'), + 'priority': KeyInfo(default='8/8'), + 'queue': KeyInfo(default='default-small/default-small'), + 'target': KeyInfo(required=True), + }, + ), + ), ('queue', 'tree'): APIData( unversioned=VersionedAPIData( primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index f9a3946..29c977b 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -180,6 +180,7 @@ options: - ppp aaa - ppp profile - queue interface + - queue simple - queue tree - radius - radius incoming diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index d717500..16c1f2f 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -189,6 +189,7 @@ options: - ppp aaa - ppp profile - queue interface + - queue simple - queue tree - radius - radius incoming From 99581a00f74d355deb03952641acdf67de678331 Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 06:58:06 +0930 Subject: [PATCH 220/365] Fix IPv6 address 'from-pool' default value (#270) * Fix ipv6 address 'from-pool' default value * Add changelog fragment for #270 --- changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml | 2 ++ plugins/module_utils/_api_data.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml diff --git a/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml b/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml new file mode 100644 index 0000000..30e99ca --- /dev/null +++ b/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 address`` (https://github.com/ansible-collections/community.routeros/pull/270). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0b06cc5..4204052 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1397,7 +1397,7 @@ PATHS = { 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'eui-64': KeyInfo(default=False), - 'from-pool': KeyInfo(), + 'from-pool': KeyInfo(default=''), 'interface': KeyInfo(required=True), 'no-dad': KeyInfo(default=False), }, From 59f659162147f399af054e922b7fd09bb9575e07 Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 06:58:40 +0930 Subject: [PATCH 221/365] Add RouterOS 7.x support to '/mpls ldp' path (#271) * Added RouterOS 7.x support to '/mpls ldp' path * Updated /mpls ldp path - Reordered fields to match CLI - Set 'vrf' field as primary key - Fixed distribute-for-default field - Added missing fields from RouterOS 7.x * Add changelog fragment --- .../271-mpls_ldp_routeros_7_support.yml | 2 + plugins/module_utils/_api_data.py | 48 +++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 changelogs/fragments/271-mpls_ldp_routeros_7_support.yml diff --git a/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml b/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml new file mode 100644 index 0000000..c8a8ebd --- /dev/null +++ b/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 4204052..e6f747e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3602,20 +3602,40 @@ PATHS = { ), ), ('mpls', 'ldp'): APIData( - unversioned=VersionedAPIData( - single_value=True, - fully_understood=True, - fields={ - 'distribute-for-default-route': KeyInfo(default=False), - 'enabled': KeyInfo(default=False), - 'hop-limit': KeyInfo(default=255), - 'loop-detect': KeyInfo(default=False), - 'lsr-id': KeyInfo(default='0.0.0.0'), - 'path-vector-limit': KeyInfo(default=255), - 'transport-address': KeyInfo(default='0.0.0.0'), - 'use-explicit-null': KeyInfo(default=False), - }, - ), + versioned=[ + ('7.1', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('vrf', ), + fields={ + 'afi': KeyInfo(can_disable=True), + 'distribute-for-default': KeyInfo(can_disable=True), + 'path-vector-limit': KeyInfo(can_disable=True), + 'vrf': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'hop-limit': KeyInfo(can_disable=True), + 'preferred-afi': KeyInfo(can_disable=True), + 'loop-detect': KeyInfo(can_disable=True), + 'transport-addresses': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'lsr-id': KeyInfo(can_disable=True), + 'use-explicit-null': KeyInfo(can_disable=True), + }, + )), + ('7.1', '<', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'distribute-for-default-route': KeyInfo(default=False), + 'enabled': KeyInfo(default=False), + 'hop-limit': KeyInfo(default=255), + 'loop-detect': KeyInfo(default=False), + 'lsr-id': KeyInfo(default='0.0.0.0'), + 'path-vector-limit': KeyInfo(default=255), + 'transport-address': KeyInfo(default='0.0.0.0'), + 'use-explicit-null': KeyInfo(default=False), + }, + )), + ], ), ('port', 'firmware'): APIData( unversioned=VersionedAPIData( From 62a795f9950adc46ff8840f466dbb15615bee729 Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 06:59:57 +0930 Subject: [PATCH 222/365] Add support for '/interface pppoe-server server' path (#273) * Add support for '/interface pppoe-server server' path * Fixed one-session-per-host default value * Add changelogs/fragments/273-add_interface_pppoe-server_support.yml --- ...273-add_interface_pppoe-server_support.yml | 2 ++ plugins/module_utils/_api_data.py | 22 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 26 insertions(+) create mode 100644 changelogs/fragments/273-add_interface_pppoe-server_support.yml diff --git a/changelogs/fragments/273-add_interface_pppoe-server_support.yml b/changelogs/fragments/273-add_interface_pppoe-server_support.yml new file mode 100644 index 0000000..dbd43f3 --- /dev/null +++ b/changelogs/fragments/273-add_interface_pppoe-server_support.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/interface pppoe-server server`` (https://github.com/ansible-collections/community.routeros/pull/273). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e6f747e..892eca2 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1497,6 +1497,28 @@ PATHS = { }, ), ), + ('interface', 'pppoe-server', 'server'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'accept-empty-service': KeyInfo(default=True), + 'authentication': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-profile': KeyInfo(default='default'), + 'disabled': KeyInfo(default=True), + 'interface': KeyInfo(required=True), + 'keepalive-timeout': KeyInfo(default=10), + 'max-mru': KeyInfo(default='auto'), + 'max-mtu': KeyInfo(default='auto'), + 'max-sessions': KeyInfo(default='unlimited'), + 'mrru': KeyInfo(default='disabled'), + 'one-session-per-host': KeyInfo(default=False), + 'pado-delay': KeyInfo(default=0), + 'service-name': KeyInfo(default=''), + }, + ), + ), ('interface', 'pptp-server', 'server'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 29c977b..fb6a08f 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -75,6 +75,7 @@ options: - interface ovpn-server server - interface ppp-client - interface pppoe-client + - interface pppoe-server server - interface pptp-server server - interface sstp-server server - interface vlan diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 16c1f2f..8f40a7c 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -84,6 +84,7 @@ options: - interface ovpn-server server - interface ppp-client - interface pppoe-client + - interface pppoe-server server - interface pptp-server server - interface sstp-server server - interface vlan From 78d2fdd0f29c6f7e0c309090ae60f6cf437c5009 Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 07:00:14 +0930 Subject: [PATCH 223/365] Add support for '/queue type' path (#274) * Add support for '/queue type' path * Add changelogs/fragments/274-add_queue_type_path.yml --- .../fragments/274-add_queue_type_path.yml | 2 + plugins/module_utils/_api_data.py | 87 ++++++++++++------- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 changelogs/fragments/274-add_queue_type_path.yml diff --git a/changelogs/fragments/274-add_queue_type_path.yml b/changelogs/fragments/274-add_queue_type_path.yml new file mode 100644 index 0000000..8406b3f --- /dev/null +++ b/changelogs/fragments/274-add_queue_type_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 892eca2..4718a63 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4326,6 +4326,64 @@ PATHS = { }, ), ), + ('queue', 'type'): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'name': KeyInfo(), + 'kind': KeyInfo(required=True), + 'bfifo-limit': KeyInfo(default=15000), + 'cake-ack-filter': KeyInfo(default='none'), + 'cake-atm': KeyInfo(default='none'), + 'cake-autorate-ingress': KeyInfo(can_disable=True), + 'cake-bandwidth': KeyInfo(can_disable=True, remove_value=0), + 'cake-diffserv': KeyInfo(default='diffserv3'), + 'cake-flowmode': KeyInfo(default='triple-isolate'), + 'cake-memlimit': KeyInfo(default=0), + 'cake-mpu': KeyInfo(can_disable=True, remove_value=''), + 'cake-nat': KeyInfo(can_disable=True, remove_value=False), + 'cake-overhead': KeyInfo(default=0), + 'cake-overhead-scheme': KeyInfo(can_disable=True, remove_value=''), + 'cake-rtt': KeyInfo(default='100ms'), + 'cake-rtt-scheme': KeyInfo(default='none'), + 'cake-wash': KeyInfo(can_disable=True, remove_value=False), + 'codel-ce-threshold': KeyInfo(can_disable=True, remove_value=''), + 'codel-ecn': KeyInfo(can_disable=True, remove_value=False), + 'codel-interval': KeyInfo(default='100ms'), + 'codel-limit': KeyInfo(default=1000), + 'codel-target': KeyInfo(default='5ms'), + 'fq-codel-ce-threshold': KeyInfo(can_disable=True, remove_value=''), + 'fq-codel-ecn': KeyInfo(default=True), + 'fq-codel-flows': KeyInfo(default=1024), + 'fq-codel-interval': KeyInfo(default='100ms'), + 'fq-codel-limit': KeyInfo(default=10240), + 'fq-codel-memlimit': KeyInfo(default=33554432), + 'fq-codel-quantum': KeyInfo(default=1514), + 'fq-codel-target': KeyInfo(default='5ms'), + 'mq-pfifo-limit': KeyInfo(default=50), + 'pcq-burst-rate': KeyInfo(default=0), + 'pcq-burst-threshold': KeyInfo(default=0), + 'pcq-burst-time': KeyInfo(default='10s'), + 'pcq-classifier': KeyInfo(can_disable=True, remove_value=''), + 'pcq-dst-address-mask': KeyInfo(default=32), + 'pcq-dst-address6-mask': KeyInfo(default=128), + 'pcq-limit': KeyInfo(default=50), + 'pcq-rate': KeyInfo(default=0), + 'pcq-src-address-mask': KeyInfo(default=32), + 'pcq-src-address6-mask': KeyInfo(default=128), + 'pcq-total-limit': KeyInfo(default=2000), + 'pfifo-limit': KeyInfo(default=50), + 'red-avg-packet': KeyInfo(default=1000), + 'red-burst': KeyInfo(default=20), + 'red-limit': KeyInfo(default=60), + 'red-max-threshold': KeyInfo(default=50), + 'red-min-threshold': KeyInfo(default=10), + 'sfq-allot': KeyInfo(default=1514), + 'sfq-perturb': KeyInfo(default=5), + }, + ), + ), ('interface', 'ethernet', 'switch'): APIData( unversioned=VersionedAPIData( fixed_entries=True, @@ -4401,35 +4459,6 @@ PATHS = { }, ), ), - ('queue', 'type'): APIData( - unversioned=VersionedAPIData( - has_identifier=True, - fields={ - 'kind': KeyInfo(), - 'mq-pfifo-limit': KeyInfo(), - 'name': KeyInfo(), - 'pcq-burst-rate': KeyInfo(), - 'pcq-burst-threshold': KeyInfo(), - 'pcq-burst-time': KeyInfo(), - 'pcq-classifier': KeyInfo(), - 'pcq-dst-address-mask': KeyInfo(), - 'pcq-dst-address6-mask': KeyInfo(), - 'pcq-limit': KeyInfo(), - 'pcq-rate': KeyInfo(), - 'pcq-src-address-mask': KeyInfo(), - 'pcq-src-address6-mask': KeyInfo(), - 'pcq-total-limit': KeyInfo(), - 'pfifo-limit': KeyInfo(), - 'red-avg-packet': KeyInfo(), - 'red-burst': KeyInfo(), - 'red-limit': KeyInfo(), - 'red-max-threshold': KeyInfo(), - 'red-min-threshold': KeyInfo(), - 'sfq-allot': KeyInfo(), - 'sfq-perturb': KeyInfo(), - }, - ), - ), ('routing', 'bgp', 'connection'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index fb6a08f..bbb0bd1 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -183,6 +183,7 @@ options: - queue interface - queue simple - queue tree + - queue type - radius - radius incoming - routing bgp connection diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 8f40a7c..87a1184 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -192,6 +192,7 @@ options: - queue interface - queue simple - queue tree + - queue type - radius - radius incoming - routing bgp connection From 6fde8f3baf6dc03cbd3d3d6bea5c313705c36186 Mon Sep 17 00:00:00 2001 From: samburney Date: Thu, 18 Apr 2024 15:25:57 +0930 Subject: [PATCH 224/365] Add support for additional '/mpls' paths (#272) * Add support for additional '/mpls' paths - Enable '/mpls interface' for use in api_info/api_modify and update fields. - Add '/mpls ldp accept-filter' path. - Add '/mpls ldp advertise-filter' path. - Add '/mpls ldp interface' path. * Add changelogs/fragments/272-additional_mpls_path_support.yml * Fixed new paths in api_info.py and api_modify.py * Remove dot. --------- Co-authored-by: Felix Fontein --- .../272-additional_mpls_path_support.yml | 2 + plugins/module_utils/_api_data.py | 51 +++++++++++++++++-- plugins/modules/api_info.py | 4 ++ plugins/modules/api_modify.py | 4 ++ 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/272-additional_mpls_path_support.yml diff --git a/changelogs/fragments/272-additional_mpls_path_support.yml b/changelogs/fragments/272-additional_mpls_path_support.yml new file mode 100644 index 0000000..594ea53 --- /dev/null +++ b/changelogs/fragments/272-additional_mpls_path_support.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` (https://github.com/ansible-collections/community.routeros/pull/272). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 4718a63..9945a2c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3613,13 +3613,13 @@ PATHS = { ), ('mpls', 'interface'): APIData( unversioned=VersionedAPIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'interface': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'interface': KeyInfo(required=True), 'mpls-mtu': KeyInfo(), + 'info': KeyInfo(can_disable=True), }, ), ), @@ -3659,6 +3659,47 @@ PATHS = { )), ], ), + ('mpls', 'ldp', 'accept-filter'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'accept': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'neighbor': KeyInfo(can_disable=True), + 'prefix': KeyInfo(can_disable=True), + 'vrf': KeyInfo(can_disable=True), + }, + ), + ), + ('mpls', 'ldp', 'advertise-filter'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'advertise': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'neighbor': KeyInfo(), + 'prefix': KeyInfo(), + 'vrf': KeyInfo(), + }, + ), + ), + ('mpls', 'ldp', 'interface'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'accept-dynamic-neighbors': KeyInfo(can_disable=True), + 'afi': KeyInfo(can_disable=True), + 'hello-interval': KeyInfo(can_disable=True), + 'hold-time': KeyInfo(can_disable=True), + 'interface': KeyInfo(required=True), + 'transport-addresses': KeyInfo(can_disable=True), + }, + ), + ), ('port', 'firmware'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index bbb0bd1..c2260a9 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -175,7 +175,11 @@ options: - ipv6 route - ipv6 settings - mpls + - mpls interface - mpls ldp + - mpls ldp accept-filter + - mpls ldp advertise-filter + - mpls ldp interface - port firmware - port remote-access - ppp aaa diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 87a1184..5224d68 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -184,7 +184,11 @@ options: - ipv6 route - ipv6 settings - mpls + - mpls interface - mpls ldp + - mpls ldp accept-filter + - mpls ldp advertise-filter + - mpls ldp interface - port firmware - port remote-access - ppp aaa From 55817c112aa7584ec05b38e73b8a7bdca95f64a7 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 18 Apr 2024 07:57:07 +0200 Subject: [PATCH 225/365] Prepare 2.15.0 release. --- changelogs/fragments/2.15.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.15.0.yml diff --git a/changelogs/fragments/2.15.0.yml b/changelogs/fragments/2.15.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/2.15.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index 0ddaab4..3f226f3 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.14.0 +version: 2.15.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 18deb0b46b4b0b981d9e7c12f39f2fa684d285e2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 18 Apr 2024 12:23:21 +0200 Subject: [PATCH 226/365] Include changelog in docsite. (#281) --- docs/docsite/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/docsite/config.yml diff --git a/docs/docsite/config.yml b/docs/docsite/config.yml new file mode 100644 index 0000000..1d6cf85 --- /dev/null +++ b/docs/docsite/config.yml @@ -0,0 +1,7 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +changelog: + write_changelog: true From c6be3918ec9f3cb6229e42c9721170a1a05991eb Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:29:25 +0400 Subject: [PATCH 227/365] Add support for '/ip dhcp-relay' path (#276) * Add support for '/ip dhcp-relay' path * add changelogs fragments --- .../fragments/276-add_ip_dhcp-relay_path.yml | 2 ++ plugins/module_utils/_api_data.py | 16 ++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/276-add_ip_dhcp-relay_path.yml diff --git a/changelogs/fragments/276-add_ip_dhcp-relay_path.yml b/changelogs/fragments/276-add_ip_dhcp-relay_path.yml new file mode 100644 index 0000000..a5d41d2 --- /dev/null +++ b/changelogs/fragments/276-add_ip_dhcp-relay_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9945a2c..a39edf8 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2579,6 +2579,22 @@ PATHS = { }, ), ), + ('ip', 'dhcp-relay'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'add-relay-info': KeyInfo(default=False), + 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), + 'dhcp-server': KeyInfo(required=True), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'local-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'name': KeyInfo(), + 'relay-info-remote-id': KeyInfo(), + }, + ), + ), ('ip', 'dhcp-server', 'config'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index c2260a9..1fb4d7b 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -121,6 +121,7 @@ options: - ip cloud advanced - ip dhcp-client - ip dhcp-client option + - ip dhcp-relay - ip dhcp-server - ip dhcp-server config - ip dhcp-server lease diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 5224d68..9b41a5b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -130,6 +130,7 @@ options: - ip cloud advanced - ip dhcp-client - ip dhcp-client option + - ip dhcp-relay - ip dhcp-server - ip dhcp-server config - ip dhcp-server lease From 018125ddfa3d8205f6b98052b65dd89bfd899a38 Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:29:44 +0400 Subject: [PATCH 228/365] Add support for '/routing bgp' paths (#277) * Add support for '/routing bgp' paths * resolve conflicts * add changelogs fragments --- .../fragments/277-add_routing_bgp_paths.yml | 2 + plugins/module_utils/_api_data.py | 64 +++++++++++++++++++ plugins/modules/api_info.py | 3 + plugins/modules/api_modify.py | 3 + 4 files changed, 72 insertions(+) create mode 100644 changelogs/fragments/277-add_routing_bgp_paths.yml diff --git a/changelogs/fragments/277-add_routing_bgp_paths.yml b/changelogs/fragments/277-add_routing_bgp_paths.yml new file mode 100644 index 0000000..751bf79 --- /dev/null +++ b/changelogs/fragments/277-add_routing_bgp_paths.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index a39edf8..b8e6db3 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4516,6 +4516,23 @@ PATHS = { }, ), ), + ('routing', 'bgp', 'aggregate'): APIData( + unversioned=VersionedAPIData( + primary_keys=('prefix',), + fully_understood=True, + fields={ + 'advertise-filter': KeyInfo(), + 'attribute-filter': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'include-igp': KeyInfo(default=False), + 'inherit-attributes': KeyInfo(default=True), + 'instance': KeyInfo(required=True), + 'prefix': KeyInfo(required=True), + 'summary-only': KeyInfo(default=True), + 'suppress-filter': KeyInfo(), + }, + ), + ), ('routing', 'bgp', 'connection'): APIData( unversioned=VersionedAPIData( fully_understood=True, @@ -4600,6 +4617,53 @@ PATHS = { }, ), ), + ('routing', 'bgp', 'network'): APIData( + unversioned=VersionedAPIData( + primary_keys=('network',), + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'network': KeyInfo(required=True), + 'synchronize': KeyInfo(default=True), + }, + ), + ), + ('routing', 'bgp', 'peer'): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'address-families': KeyInfo(default='ip'), + 'allow-as-in': KeyInfo(can_disable=True, remove_value=''), + 'as-override': KeyInfo(default=False), + 'cisco-vpls-nlri-len-fmt': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-originate': KeyInfo(default='never'), + 'disabled': KeyInfo(default=False), + 'hold-time': KeyInfo(default='3m'), + 'in-filter': KeyInfo(), + 'instance': KeyInfo(), + 'keepalive-time': KeyInfo(can_disable=True, remove_value=''), + 'max-prefix-limit': KeyInfo(can_disable=True, remove_value=''), + 'max-prefix-restart-time': KeyInfo(can_disable=True, remove_value=''), + 'multihop': KeyInfo(default=False), + 'name': KeyInfo(), + 'nexthop-choice': KeyInfo(default='default'), + 'passive': KeyInfo(default=False), + 'out-filter': KeyInfo(), + 'remote-address': KeyInfo(required=True), + 'remote-as': KeyInfo(required=True), + 'remote-port': KeyInfo(can_disable=True, remove_value=''), + 'remove-private-as': KeyInfo(default=False), + 'route-reflect': KeyInfo(default=False), + 'tcp-md5-key': KeyInfo(), + 'ttl': KeyInfo(default='default'), + 'update-source': KeyInfo(can_disable=True, remove_value='none'), + 'use-bfd': KeyInfo(default=False), + }, + ), + ), ('routing', 'bgp', 'template'): APIData( unversioned=VersionedAPIData( primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 1fb4d7b..37bc51d 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -191,8 +191,11 @@ options: - queue type - radius - radius incoming + - routing bgp aggregate - routing bgp connection - routing bgp instance + - routing bgp network + - routing bgp peer - routing bgp template - routing filter rule - routing filter select-rule diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 9b41a5b..3ae0740 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -200,8 +200,11 @@ options: - queue type - radius - radius incoming + - routing bgp aggregate - routing bgp connection - routing bgp instance + - routing bgp network + - routing bgp peer - routing bgp template - routing filter rule - routing filter select-rule From 9d34cca66b6b4e5c5c76636b89c2b00d20a8d707 Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:29:58 +0400 Subject: [PATCH 229/365] Add RouterOS 6.x support for '/ip route rule' path (#278) * Add RouterOS 6.x support for '/ip route rule' path * add changelogs fragments --- .../fragments/278-add_ip_route_rule_path.yml | 2 ++ plugins/module_utils/_api_data.py | 17 +++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 21 insertions(+) create mode 100644 changelogs/fragments/278-add_ip_route_rule_path.yml diff --git a/changelogs/fragments/278-add_ip_route_rule_path.yml b/changelogs/fragments/278-add_ip_route_rule_path.yml new file mode 100644 index 0000000..9c559bf --- /dev/null +++ b/changelogs/fragments/278-add_ip_route_rule_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index b8e6db3..18fb37c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -729,6 +729,23 @@ PATHS = { }, ), ), + ('ip', 'route', 'rule'): APIData( + versioned=[ + ('7', '<', VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='lookup'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dst-address': KeyInfo(can_disable=True), + 'interface': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'src-address': KeyInfo(can_disable=True), + 'table': KeyInfo(default='main'), + }, + )), + ], + ), ('ip', 'vrf'): APIData( versioned=[ ('7', '>=', VersionedAPIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 37bc51d..cbed689 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -149,6 +149,7 @@ options: - ip pool - ip proxy - ip route + - ip route rule - ip route vrf - ip service - ip settings diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 3ae0740..05b45ad 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -158,6 +158,7 @@ options: - ip pool - ip proxy - ip route + - ip route rule - ip route vrf - ip service - ip settings From 4a078c5913c73306b425817f540b887824f1f048 Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:30:25 +0400 Subject: [PATCH 230/365] Add RouterOS 6.x support for '/routing filter' path (#279) * Add RouterOS 6.x support for '/routing filter' path * add changelogs fragments --- .../fragments/279-add_routing_filter_path.yml | 2 + plugins/module_utils/_api_data.py | 67 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 71 insertions(+) create mode 100644 changelogs/fragments/279-add_routing_filter_path.yml diff --git a/changelogs/fragments/279-add_routing_filter_path.yml b/changelogs/fragments/279-add_routing_filter_path.yml new file mode 100644 index 0000000..08dc36a --- /dev/null +++ b/changelogs/fragments/279-add_routing_filter_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 18fb37c..fdf5cba 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -804,6 +804,73 @@ PATHS = { }, ), ), + ('routing', 'filter'): APIData( + versioned=[ + ('7', '<', VersionedAPIData( + fully_understood=True, + fields={ + 'action': KeyInfo(default='passthrough'), + 'address-family': KeyInfo(can_disable=True), + 'append-bgp-communities': KeyInfo(can_disable=True), + 'append-route-targets': KeyInfo(can_disable=True), + 'bgp-as-path': KeyInfo(can_disable=True), + 'bgp-as-path-length': KeyInfo(can_disable=True), + 'bgp-atomic-aggregate': KeyInfo(can_disable=True), + 'bgp-communities': KeyInfo(can_disable=True), + 'bgp-local-pref': KeyInfo(can_disable=True), + 'bgp-med': KeyInfo(can_disable=True), + 'bgp-origin': KeyInfo(can_disable=True), + 'bgp-weight': KeyInfo(can_disable=True), + 'chain': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'distance': KeyInfo(can_disable=True), + 'invert-match': KeyInfo(default=False), + 'jump-target': KeyInfo(), + 'locally-originated-bgp': KeyInfo(can_disable=True), + 'match-chain': KeyInfo(can_disable=True), + 'ospf-type': KeyInfo(can_disable=True), + 'pref-src': KeyInfo(can_disable=True), + 'prefix': KeyInfo(default='0.0.0.0/0'), + 'prefix-length': KeyInfo(can_disable=True), + 'protocol': KeyInfo(can_disable=True), + 'route-comment': KeyInfo(can_disable=True), + 'route-tag': KeyInfo(can_disable=True), + 'route-targets': KeyInfo(can_disable=True), + 'routing-mark': KeyInfo(can_disable=True), + 'scope': KeyInfo(can_disable=True), + 'set-bgp-communities': KeyInfo(can_disable=True), + 'set-bgp-local-pref': KeyInfo(can_disable=True), + 'set-bgp-med': KeyInfo(can_disable=True), + 'set-bgp-prepend': KeyInfo(can_disable=True), + 'set-bgp-prepend-path': KeyInfo(), + 'set-bgp-weight': KeyInfo(can_disable=True), + 'set-check-gateway': KeyInfo(can_disable=True), + 'set-disabled': KeyInfo(can_disable=True), + 'set-distance': KeyInfo(can_disable=True), + 'set-in-nexthop': KeyInfo(can_disable=True), + 'set-in-nexthop-direct': KeyInfo(can_disable=True), + 'set-in-nexthop-ipv6': KeyInfo(can_disable=True), + 'set-in-nexthop-linklocal': KeyInfo(can_disable=True), + 'set-out-nexthop': KeyInfo(can_disable=True), + 'set-out-nexthop-ipv6': KeyInfo(can_disable=True), + 'set-out-nexthop-linklocal': KeyInfo(can_disable=True), + 'set-pref-src': KeyInfo(can_disable=True), + 'set-route-comment': KeyInfo(can_disable=True), + 'set-route-tag': KeyInfo(can_disable=True), + 'set-route-targets': KeyInfo(can_disable=True), + 'set-routing-mark': KeyInfo(can_disable=True), + 'set-scope': KeyInfo(can_disable=True), + 'set-site-of-origin': KeyInfo(can_disable=True), + 'set-target-scope': KeyInfo(can_disable=True), + 'set-type': KeyInfo(can_disable=True), + 'set-use-te-nexthop': KeyInfo(can_disable=True), + 'site-of-origin': KeyInfo(can_disable=True), + 'target-scope': KeyInfo(can_disable=True), + }, + )), + ], + ), ('routing', 'filter', 'rule'): APIData( versioned=[ ('7', '>=', VersionedAPIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index cbed689..a3e800e 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -198,6 +198,7 @@ options: - routing bgp network - routing bgp peer - routing bgp template + - routing filter - routing filter rule - routing filter select-rule - routing id diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 05b45ad..cd5b3a9 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -207,6 +207,7 @@ options: - routing bgp network - routing bgp peer - routing bgp template + - routing filter - routing filter rule - routing filter select-rule - routing id From 3862d1cea7cadd3a4a862e64f9b94bde59d29a17 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 20 Apr 2024 11:48:35 +0200 Subject: [PATCH 231/365] Release 2.15.0. --- CHANGELOG.md | 193 ++++++++++-------- CHANGELOG.rst | 22 ++ changelogs/changelog.yaml | 32 +++ changelogs/fragments/2.15.0.yml | 1 - .../fragments/269-add-queue_simple-path.yml | 2 - .../270_fix_ipv6_from_pool_default_value.yml | 2 - .../271-mpls_ldp_routeros_7_support.yml | 2 - .../272-additional_mpls_path_support.yml | 2 - ...273-add_interface_pppoe-server_support.yml | 2 - .../fragments/274-add_queue_type_path.yml | 2 - .../fragments/276-add_ip_dhcp-relay_path.yml | 2 - .../fragments/277-add_routing_bgp_paths.yml | 2 - .../fragments/278-add_ip_route_rule_path.yml | 2 - .../fragments/279-add_routing_filter_path.yml | 2 - 14 files changed, 163 insertions(+), 105 deletions(-) delete mode 100644 changelogs/fragments/2.15.0.yml delete mode 100644 changelogs/fragments/269-add-queue_simple-path.yml delete mode 100644 changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml delete mode 100644 changelogs/fragments/271-mpls_ldp_routeros_7_support.yml delete mode 100644 changelogs/fragments/272-additional_mpls_path_support.yml delete mode 100644 changelogs/fragments/273-add_interface_pppoe-server_support.yml delete mode 100644 changelogs/fragments/274-add_queue_type_path.yml delete mode 100644 changelogs/fragments/276-add_ip_dhcp-relay_path.yml delete mode 100644 changelogs/fragments/277-add_routing_bgp_paths.yml delete mode 100644 changelogs/fragments/278-add_ip_route_rule_path.yml delete mode 100644 changelogs/fragments/279-add_routing_filter_path.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 99d0bbe..adb4f74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,106 +2,109 @@ **Topics** -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v2\.14\.0 + +## v2\.15\.0 ### Release Summary @@ -111,6 +114,28 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. +* api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. +* api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. +* api\_info\, api\_modify \- add default value for from\-pool field in /ipv6 address \([https\://github\.com/ansible\-collections/community\.routeros/pull/270](https\://github\.com/ansible\-collections/community\.routeros/pull/270)\)\. +* api\_info\, api\_modify \- add missing path /interface pppoe\-server server \([https\://github\.com/ansible\-collections/community\.routeros/pull/273](https\://github\.com/ansible\-collections/community\.routeros/pull/273)\)\. +* api\_info\, api\_modify \- add missing path /ip dhcp\-relay \([https\://github\.com/ansible\-collections/community\.routeros/pull/276](https\://github\.com/ansible\-collections/community\.routeros/pull/276)\)\. +* api\_info\, api\_modify \- add missing path /queue simple \([https\://github\.com/ansible\-collections/community\.routeros/pull/269](https\://github\.com/ansible\-collections/community\.routeros/pull/269)\)\. +* api\_info\, api\_modify \- add missing path /queue type \([https\://github\.com/ansible\-collections/community\.routeros/pull/274](https\://github\.com/ansible\-collections/community\.routeros/pull/274)\)\. +* api\_info\, api\_modify \- add missing paths /routing bgp aggregate\, /routing bgp network and /routing bgp peer \([https\://github\.com/ansible\-collections/community\.routeros/pull/277](https\://github\.com/ansible\-collections/community\.routeros/pull/277)\)\. +* api\_info\, api\_modify \- add support for paths /mpls interface\, /mpls ldp accept\-filter\, /mpls ldp advertise\-filter and mpls ldp interface \([https\://github\.com/ansible\-collections/community\.routeros/pull/272](https\://github\.com/ansible\-collections/community\.routeros/pull/272)\)\. + + +## v2\.14\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. * api\_info\, api\_modify \- added support for interface wifi and its sub\-paths \([https\://github\.com/ansible\-collections/community\.routeros/pull/266](https\://github\.com/ansible\-collections/community\.routeros/pull/266)\)\. * api\_info\, api\_modify \- remove default value for read\-only running field in interface wireless \([https\://github\.com/ansible\-collections/community\.routeros/pull/264](https\://github\.com/ansible\-collections/community\.routeros/pull/264)\)\. @@ -118,12 +143,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -137,12 +162,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -156,12 +181,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -176,12 +201,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -213,12 +238,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -232,7 +257,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -253,7 +278,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -266,7 +291,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -279,12 +304,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -304,12 +329,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -322,12 +347,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -342,12 +367,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -360,12 +385,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -404,7 +429,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -417,12 +442,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -437,7 +462,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -451,12 +476,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -475,12 +500,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -504,12 +529,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -545,12 +570,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -566,12 +591,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -580,7 +605,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -593,7 +618,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -606,7 +631,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -619,12 +644,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c7cc6ef..1b3a760 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,28 @@ Community RouterOS Release Notes .. contents:: Topics +v2.15.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). +- api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). +- api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). +- api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 address`` (https://github.com/ansible-collections/community.routeros/pull/270). +- api_info, api_modify - add missing path ``/interface pppoe-server server`` (https://github.com/ansible-collections/community.routeros/pull/273). +- api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). +- api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). +- api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). +- api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). +- api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` (https://github.com/ansible-collections/community.routeros/pull/272). + v2.14.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index e23348b..62320dd 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -339,6 +339,38 @@ releases: - 264-wireless-running-default.yml - 266-interface-wifi.yml release_date: '2024-03-25' + 2.15.0: + changes: + minor_changes: + - api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). + - api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). + - api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). + - api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 + address`` (https://github.com/ansible-collections/community.routeros/pull/270). + - api_info, api_modify - add missing path ``/interface pppoe-server server`` + (https://github.com/ansible-collections/community.routeros/pull/273). + - api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). + - api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). + - api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). + - api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing + bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). + - api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls + ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` + (https://github.com/ansible-collections/community.routeros/pull/272). + release_summary: Feature release. + fragments: + - 2.15.0.yml + - 269-add-queue_simple-path.yml + - 270_fix_ipv6_from_pool_default_value.yml + - 271-mpls_ldp_routeros_7_support.yml + - 272-additional_mpls_path_support.yml + - 273-add_interface_pppoe-server_support.yml + - 274-add_queue_type_path.yml + - 276-add_ip_dhcp-relay_path.yml + - 277-add_routing_bgp_paths.yml + - 278-add_ip_route_rule_path.yml + - 279-add_routing_filter_path.yml + release_date: '2024-04-20' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.15.0.yml b/changelogs/fragments/2.15.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/2.15.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/269-add-queue_simple-path.yml b/changelogs/fragments/269-add-queue_simple-path.yml deleted file mode 100644 index f943de5..0000000 --- a/changelogs/fragments/269-add-queue_simple-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). \ No newline at end of file diff --git a/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml b/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml deleted file mode 100644 index 30e99ca..0000000 --- a/changelogs/fragments/270_fix_ipv6_from_pool_default_value.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 address`` (https://github.com/ansible-collections/community.routeros/pull/270). \ No newline at end of file diff --git a/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml b/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml deleted file mode 100644 index c8a8ebd..0000000 --- a/changelogs/fragments/271-mpls_ldp_routeros_7_support.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). \ No newline at end of file diff --git a/changelogs/fragments/272-additional_mpls_path_support.yml b/changelogs/fragments/272-additional_mpls_path_support.yml deleted file mode 100644 index 594ea53..0000000 --- a/changelogs/fragments/272-additional_mpls_path_support.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` (https://github.com/ansible-collections/community.routeros/pull/272). \ No newline at end of file diff --git a/changelogs/fragments/273-add_interface_pppoe-server_support.yml b/changelogs/fragments/273-add_interface_pppoe-server_support.yml deleted file mode 100644 index dbd43f3..0000000 --- a/changelogs/fragments/273-add_interface_pppoe-server_support.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/interface pppoe-server server`` (https://github.com/ansible-collections/community.routeros/pull/273). \ No newline at end of file diff --git a/changelogs/fragments/274-add_queue_type_path.yml b/changelogs/fragments/274-add_queue_type_path.yml deleted file mode 100644 index 8406b3f..0000000 --- a/changelogs/fragments/274-add_queue_type_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). \ No newline at end of file diff --git a/changelogs/fragments/276-add_ip_dhcp-relay_path.yml b/changelogs/fragments/276-add_ip_dhcp-relay_path.yml deleted file mode 100644 index a5d41d2..0000000 --- a/changelogs/fragments/276-add_ip_dhcp-relay_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). \ No newline at end of file diff --git a/changelogs/fragments/277-add_routing_bgp_paths.yml b/changelogs/fragments/277-add_routing_bgp_paths.yml deleted file mode 100644 index 751bf79..0000000 --- a/changelogs/fragments/277-add_routing_bgp_paths.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). \ No newline at end of file diff --git a/changelogs/fragments/278-add_ip_route_rule_path.yml b/changelogs/fragments/278-add_ip_route_rule_path.yml deleted file mode 100644 index 9c559bf..0000000 --- a/changelogs/fragments/278-add_ip_route_rule_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). \ No newline at end of file diff --git a/changelogs/fragments/279-add_routing_filter_path.yml b/changelogs/fragments/279-add_routing_filter_path.yml deleted file mode 100644 index 08dc36a..0000000 --- a/changelogs/fragments/279-add_routing_filter_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). \ No newline at end of file From 6116cde9dd8ff59c7ef05ca1e9e20e10e3cedc9c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 11 May 2024 23:12:16 +0200 Subject: [PATCH 232/365] Pass codecov token to ansible-test-gh-action. (#285) --- .github/workflows/ansible-test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index f743ae5..1be996c 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -50,6 +50,7 @@ jobs: uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} + codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: sanity # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) pre-test-cmd: |- @@ -90,6 +91,7 @@ jobs: uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} + codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: units # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) pre-test-cmd: |- @@ -157,6 +159,7 @@ jobs: uses: felixfontein/ansible-test-gh-action@main with: ansible-core-version: ${{ matrix.ansible }} + codecov-token: ${{ secrets.CODECOV_TOKEN }} integration-continue-on-error: 'false' integration-diff: 'false' integration-retry-on-error: 'true' From 24caea65d19025781e06d215fe4cce14f3b5e890 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 15 May 2024 21:47:43 +0200 Subject: [PATCH 233/365] Add REUSE badge. (#287) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e617a8f..f34a749 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ SPDX-License-Identifier: GPL-3.0-or-later --> # 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) +[![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) +[![REUSE status](https://api.reuse.software/badge/github.com/ansible-collections/community.routeros)](https://api.reuse.software/info/github.com/ansible-collections/community.routeros) Provides modules for [Ansible](https://www.ansible.com/community) to manage [MikroTik RouterOS](http://www.mikrotik-routeros.net/routeros.aspx) instances. From 1953a79942ba571e3f7f5ca9264e790561793858 Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Sat, 18 May 2024 17:58:42 +0400 Subject: [PATCH 234/365] minor changes '/interface ethernet' path fields (#288) * minor changes '/interface ethernet' path fields * add changelog fragment --- changelogs/fragments/288-interface_ethernet_values.yml | 2 ++ plugins/module_utils/_api_data.py | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/288-interface_ethernet_values.yml diff --git a/changelogs/fragments/288-interface_ethernet_values.yml b/changelogs/fragments/288-interface_ethernet_values.yml new file mode 100644 index 0000000..9a49fb8 --- /dev/null +++ b/changelogs/fragments/288-interface_ethernet_values.yml @@ -0,0 +1,2 @@ +minor_changes: + - api - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fdf5cba..cca6657 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -327,9 +327,9 @@ PATHS = { 'combo-mode': KeyInfo(can_disable=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), - 'fec-mode': KeyInfo(can_disable=True), + 'fec-mode': KeyInfo(can_disable=True, remove_value='auto'), 'full-duplex': KeyInfo(default=True), - 'l2mtu': KeyInfo(default=1598), + 'l2mtu': KeyInfo(), 'loop-protect': KeyInfo(default='default'), 'loop-protect-disable-time': KeyInfo(default='5m'), 'loop-protect-send-interval': KeyInfo(default='5s'), @@ -338,8 +338,8 @@ PATHS = { 'mtu': KeyInfo(default=1500), 'name': KeyInfo(), 'orig-mac-address': KeyInfo(), - 'poe-out': KeyInfo(can_disable=True), - 'poe-priority': KeyInfo(can_disable=True), + 'poe-out': KeyInfo(can_disable=True, remove_value='auto-on'), + 'poe-priority': KeyInfo(can_disable=True, remove_value=10), 'poe-voltage': KeyInfo(can_disable=True), 'power-cycle-interval': KeyInfo(), 'power-cycle-ping-address': KeyInfo(can_disable=True), @@ -347,7 +347,7 @@ PATHS = { 'power-cycle-ping-timeout': KeyInfo(can_disable=True), 'rx-flow-control': KeyInfo(default='off'), 'sfp-rate-select': KeyInfo(default='high'), - 'sfp-shutdown-temperature': KeyInfo(default='95C'), + 'sfp-shutdown-temperature': KeyInfo(default=95), 'speed': KeyInfo(), 'tx-flow-control': KeyInfo(default='off'), }, From 331a97b12d745604253e802937c4de1b49736a1e Mon Sep 17 00:00:00 2001 From: samburney Date: Sat, 18 May 2024 23:29:49 +0930 Subject: [PATCH 235/365] Add support for 'ppp secret' path (#286) * Add support for 'ppp secret' path * Add changelog fragment --- .../fragments/286-add_ppp_secret_path.yml | 2 ++ plugins/module_utils/_api_data.py | 21 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 25 insertions(+) create mode 100644 changelogs/fragments/286-add_ppp_secret_path.yml diff --git a/changelogs/fragments/286-add_ppp_secret_path.yml b/changelogs/fragments/286-add_ppp_secret_path.yml new file mode 100644 index 0000000..4827fb6 --- /dev/null +++ b/changelogs/fragments/286-add_ppp_secret_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index cca6657..0883a2f 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4600,6 +4600,27 @@ PATHS = { }, ), ), + ('ppp', 'secret'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'caller-id': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'ipv6-routes': KeyInfo(default=''), + 'limit-bytes-in': KeyInfo(default=0), + 'limit-bytes-out': KeyInfo(default=0), + 'local-address': KeyInfo(can_disable=True), + 'name': KeyInfo(required=True), + 'password': KeyInfo(), + 'profile': KeyInfo(default='default'), + 'remote-address': KeyInfo(can_disable=True), + 'remote-ipv6-prefix': KeyInfo(can_disable=True), + 'routes': KeyInfo(can_disable=True), + 'service': KeyInfo(default='any'), + }, + ), + ), ('routing', 'bgp', 'aggregate'): APIData( unversioned=VersionedAPIData( primary_keys=('prefix',), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index a3e800e..1d5dea5 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -186,6 +186,7 @@ options: - port remote-access - ppp aaa - ppp profile + - ppp secret - queue interface - queue simple - queue tree diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index cd5b3a9..73a08ef 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -195,6 +195,7 @@ options: - port remote-access - ppp aaa - ppp profile + - ppp secret - queue interface - queue simple - queue tree From f5e8213498e31696a2336cba661890a3b597c314 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 18 May 2024 16:30:04 +0200 Subject: [PATCH 236/365] Prepare 2.16.0. --- changelogs/fragments/2.16.0.yml | 1 + changelogs/fragments/288-interface_ethernet_values.yml | 2 +- galaxy.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/2.16.0.yml diff --git a/changelogs/fragments/2.16.0.yml b/changelogs/fragments/2.16.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/2.16.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/changelogs/fragments/288-interface_ethernet_values.yml b/changelogs/fragments/288-interface_ethernet_values.yml index 9a49fb8..a1181fc 100644 --- a/changelogs/fragments/288-interface_ethernet_values.yml +++ b/changelogs/fragments/288-interface_ethernet_values.yml @@ -1,2 +1,2 @@ minor_changes: - - api - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). \ No newline at end of file + - api_info, api_modify - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 3f226f3..f978080 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.15.0 +version: 2.16.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 6aebd8e3590bbefc292269b201d3a7a06a8a03ac Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 20 May 2024 08:45:26 +0200 Subject: [PATCH 237/365] From now on automatically add period to new plugins in changelog, and use FQCNs. (#289) --- CHANGELOG.md | 18 +++++++++--------- CHANGELOG.rst | 18 +++++++++--------- changelogs/config.yaml | 3 +++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adb4f74..408d6ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -494,8 +494,8 @@ New feature release\. ### New Modules -* api\_info \- Retrieve information from API -* api\_modify \- Modify data at paths with API +* community\.routeros\.api\_info \- Retrieve information from API +* community\.routeros\.api\_modify \- Modify data at paths with API ## v2\.1\.0 @@ -523,8 +523,8 @@ Feature and bugfix release with new modules\. ### New Modules -* api\_facts \- Collect facts from remote devices running MikroTik RouterOS using the API -* api\_find\_and\_modify \- Find and modify information using the API +* community\.routeros\.api\_facts \- Collect facts from remote devices running MikroTik RouterOS using the API +* community\.routeros\.api\_find\_and\_modify \- Find and modify information using the API ## v2\.0\.0 @@ -561,11 +561,11 @@ A new major release with breaking changes in the behavior of community\.ro #### Filter -* join \- Join a list of arguments to a command -* list\_to\_dict \- Convert a list of arguments to a list of dictionary -* quote\_argument \- Quote an argument -* quote\_argument\_value \- Quote an argument value -* split \- Split a command into arguments +* community\.routeros\.join \- Join a list of arguments to a command +* community\.routeros\.list\_to\_dict \- Convert a list of arguments to a list of dictionary +* community\.routeros\.quote\_argument \- Quote an argument +* community\.routeros\.quote\_argument\_value \- Quote an argument value +* community\.routeros\.split \- Split a command into arguments ## v1\.2\.0 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1b3a760..f88e33b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -396,8 +396,8 @@ Bugfixes New Modules ----------- -- api_info - Retrieve information from API -- api_modify - Modify data at paths with API +- community.routeros.api_info - Retrieve information from API +- community.routeros.api_modify - Modify data at paths with API v2.1.0 ====== @@ -425,8 +425,8 @@ Bugfixes New Modules ----------- -- api_facts - Collect facts from remote devices running MikroTik RouterOS using the API -- api_find_and_modify - Find and modify information using the API +- community.routeros.api_facts - Collect facts from remote devices running MikroTik RouterOS using the API +- community.routeros.api_find_and_modify - Find and modify information using the API v2.0.0 ====== @@ -463,11 +463,11 @@ New Plugins Filter ~~~~~~ -- join - Join a list of arguments to a command -- list_to_dict - Convert a list of arguments to a list of dictionary -- quote_argument - Quote an argument -- quote_argument_value - Quote an argument value -- split - Split a command into arguments +- community.routeros.join - Join a list of arguments to a command +- community.routeros.list_to_dict - Convert a list of arguments to a list of dictionary +- community.routeros.quote_argument - Quote an argument +- community.routeros.quote_argument_value - Quote an argument value +- community.routeros.split - Split a command into arguments v1.2.0 ====== diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 86412ba..bb3c08b 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -35,3 +35,6 @@ sections: - - known_issues - Known Issues title: Community RouterOS +trivial_section_name: trivial +use_fqcn: true +add_plugin_period: true From f43a5ce446a5a1afdbe81a87539dfa156f5cd21f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 4 Jun 2024 07:42:57 +0200 Subject: [PATCH 238/365] Stop building EE with CentOS Stream 8, which no longer has builds. (#290) --- .github/workflows/ee.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 523efaf..67735c3 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -70,14 +70,6 @@ jobs: package_system: python39 python39-pip python39-wheel python39-cryptography base_image: docker.io/redhat/ubi8:latest pre_base: '"#"' - - name: ansible-core 2.12 @ CentOS Stream 8 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.12.tar.gz - ansible_runner: ansible-runner - other_deps: |2 - python_interpreter: - package_system: python39 python39-pip python39-wheel python39-cryptography - base_image: quay.io/centos/centos:stream8 - pre_base: '"#"' runs-on: ubuntu-latest steps: - name: Check out code From d1be11ec08649092a050cfe14a0f38d020f6a127 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 15 Jun 2024 14:21:44 +0200 Subject: [PATCH 239/365] Use ansible-community/eol-ansible for 2.9/2.10/2.11 tests. (#292) --- .github/workflows/ansible-test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 1be996c..fa62419 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -49,6 +49,7 @@ jobs: - name: Perform sanity testing uses: felixfontein/ansible-test-gh-action@main with: + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: sanity @@ -90,6 +91,7 @@ jobs: Ansible version ${{ matrix.ansible }} uses: felixfontein/ansible-test-gh-action@main with: + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: units @@ -158,6 +160,7 @@ jobs: under Python ${{ matrix.python }} uses: felixfontein/ansible-test-gh-action@main with: + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} integration-continue-on-error: 'false' From 2f46ff03fdd91d40db3e29ec5612e8d911c92cf8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 16 Jun 2024 21:14:03 +0200 Subject: [PATCH 240/365] Release 2.16.0. --- CHANGELOG.md | 191 ++++++++++-------- CHANGELOG.rst | 14 ++ changelogs/changelog.yaml | 11 + changelogs/fragments/2.16.0.yml | 1 - .../fragments/286-add_ppp_secret_path.yml | 2 - .../288-interface_ethernet_values.yml | 2 - 6 files changed, 129 insertions(+), 92 deletions(-) delete mode 100644 changelogs/fragments/2.16.0.yml delete mode 100644 changelogs/fragments/286-add_ppp_secret_path.yml delete mode 100644 changelogs/fragments/288-interface_ethernet_values.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 408d6ca..a17b8fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,109 +2,112 @@ **Topics** -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -114,6 +117,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -128,12 +145,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -143,12 +160,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -162,12 +179,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -181,12 +198,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -201,12 +218,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -238,12 +255,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -257,7 +274,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -278,7 +295,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -291,7 +308,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -304,12 +321,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -329,12 +346,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -347,12 +364,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -367,12 +384,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -385,12 +402,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -429,7 +446,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -442,12 +459,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -462,7 +479,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -476,12 +493,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -500,12 +517,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -529,12 +546,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -570,12 +587,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -591,12 +608,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -605,7 +622,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -618,7 +635,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -631,7 +648,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -644,12 +661,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f88e33b..1a735af 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,20 @@ Community RouterOS Release Notes .. contents:: Topics +v2.16.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). +- api_info, api_modify - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). + v2.15.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 62320dd..71044fb 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -371,6 +371,17 @@ releases: - 278-add_ip_route_rule_path.yml - 279-add_routing_filter_path.yml release_date: '2024-04-20' + 2.16.0: + changes: + minor_changes: + - api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). + - api_info, api_modify - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). + release_summary: Feature release. + fragments: + - 2.16.0.yml + - 286-add_ppp_secret_path.yml + - 288-interface_ethernet_values.yml + release_date: '2024-06-16' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.16.0.yml b/changelogs/fragments/2.16.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/2.16.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/286-add_ppp_secret_path.yml b/changelogs/fragments/286-add_ppp_secret_path.yml deleted file mode 100644 index 4827fb6..0000000 --- a/changelogs/fragments/286-add_ppp_secret_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). \ No newline at end of file diff --git a/changelogs/fragments/288-interface_ethernet_values.yml b/changelogs/fragments/288-interface_ethernet_values.yml deleted file mode 100644 index a1181fc..0000000 --- a/changelogs/fragments/288-interface_ethernet_values.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). \ No newline at end of file From dc7fa11f5db7b0e63b3b8f04cdd42604fdcd0fae Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 21 Jun 2024 21:38:11 +0200 Subject: [PATCH 241/365] Stop building EE with RHEL UBI 8. (#293) --- .github/workflows/ee.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 67735c3..cd6341f 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -62,14 +62,6 @@ jobs: ansible_runner: ansible-runner base_image: quay.io/centos/centos:stream9 pre_base: '"#"' - - name: ansible-core 2.13 @ RHEL UBI 8 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.13.tar.gz - ansible_runner: ansible-runner - other_deps: |2 - python_interpreter: - package_system: python39 python39-pip python39-wheel python39-cryptography - base_image: docker.io/redhat/ubi8:latest - pre_base: '"#"' runs-on: ubuntu-latest steps: - name: Check out code From 91fef4e3a9393be1eb0ebfaa97f7cff620815893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Thu, 27 Jun 2024 11:58:24 +0200 Subject: [PATCH 242/365] Add `system health settings` path (#294) Add changelog fragment Change changelog fragment to lower-case --- .../294-add-system-health-settings-path.yml | 2 + plugins/module_utils/_api_data.py | 38 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 42 insertions(+) create mode 100644 changelogs/fragments/294-add-system-health-settings-path.yml diff --git a/changelogs/fragments/294-add-system-health-settings-path.yml b/changelogs/fragments/294-add-system-health-settings-path.yml new file mode 100644 index 0000000..13d38b4 --- /dev/null +++ b/changelogs/fragments/294-add-system-health-settings-path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0883a2f..e13b7e9 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4001,6 +4001,44 @@ PATHS = { }, ), ), + ('system', 'health', 'settings'): APIData( + versioned=[ + ('7.14', '<', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'cpu-overtemp-check': KeyInfo(), + 'cpu-overtemp-startup-delay': KeyInfo(), + 'cpu-overtemp-threshold': KeyInfo(), + 'fan-control-interval': KeyInfo(can_disable=True, default='30s'), + 'fan-full-speed-temp': KeyInfo(default=65), + 'fan-min-speed-percent': KeyInfo(default=0), + 'fan-mode': KeyInfo(), + 'fan-on-threshold': KeyInfo(), + 'fan-switch': KeyInfo(), + 'fan-target-temp': KeyInfo(default=58), + 'use-fan': KeyInfo(), + }, + )), + ('7.14', '>=', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'cpu-overtemp-check': KeyInfo(), + 'cpu-overtemp-startup-delay': KeyInfo(), + 'cpu-overtemp-threshold': KeyInfo(), + 'fan-control-interval': KeyInfo(default=30), + 'fan-full-speed-temp': KeyInfo(default=65), + 'fan-min-speed-percent': KeyInfo(default=12), + 'fan-mode': KeyInfo(), + 'fan-on-threshold': KeyInfo(), + 'fan-switch': KeyInfo(), + 'fan-target-temp': KeyInfo(default=58), + 'use-fan': KeyInfo(), + }, + )), + ], + ), ('system', 'identity'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 1d5dea5..f152a81 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -218,6 +218,7 @@ options: - snmp community - system clock - system clock manual + - system health settings - system identity - system leds settings - system logging diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 73a08ef..46ee18b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -227,6 +227,7 @@ options: - snmp community - system clock - system clock manual + - system health settings - system identity - system leds settings - system logging From a6d2580a9e50cc13a53aef9cda62003d18282c6b Mon Sep 17 00:00:00 2001 From: Igor <13848605+vint2k@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:58:54 +0400 Subject: [PATCH 243/365] Add support for '/system resource irq rps' path (#295) --- .../fragments/295-add_system_resource_irq_rps_path.yml | 2 ++ plugins/module_utils/_api_data.py | 10 ++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 14 insertions(+) create mode 100644 changelogs/fragments/295-add_system_resource_irq_rps_path.yml diff --git a/changelogs/fragments/295-add_system_resource_irq_rps_path.yml b/changelogs/fragments/295-add_system_resource_irq_rps_path.yml new file mode 100644 index 0000000..0ebacd0 --- /dev/null +++ b/changelogs/fragments/295-add_system_resource_irq_rps_path.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). \ No newline at end of file diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e13b7e9..ac9cf1b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -5004,6 +5004,16 @@ PATHS = { }, ), ), + ('system', 'resource', 'irq', 'rps'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + }, + ), + ), ('system', 'scheduler'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index f152a81..e8d8663 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -228,6 +228,7 @@ options: - system ntp client servers - system ntp server - system package update + - system resource irq rps - system routerboard settings - system scheduler - system script diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 46ee18b..5cb1cd8 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -237,6 +237,7 @@ options: - system ntp client servers - system ntp server - system package update + - system resource irq rps - system routerboard settings - system scheduler - system script From c2b43ac395c9249e1cd397b7f08e7365c6722766 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 29 Jun 2024 17:22:39 +0200 Subject: [PATCH 244/365] Adjust docs publishing workflow. (#296) Ref: https://github.com/ansible-community/github-docs-build/issues/92 --- .github/workflows/docs-pr.yml | 3 +++ .github/workflows/docs-push.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 14a917a..7d35e5c 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -40,12 +40,15 @@ jobs: if: github.repository == 'ansible-collections/community.routeros' permissions: contents: write + pages: write + id-token: write needs: [build-docs] name: Publish Ansible Docs uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main with: artifact-name: ${{ needs.build-docs.outputs.artifact-name }} action: ${{ (github.event.action == 'closed' || needs.build-docs.outputs.changed != 'true') && 'teardown' || 'publish' }} + publish-gh-pages-branch: true secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index e4595dd..80f62f5 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -43,10 +43,13 @@ jobs: if: github.repository == 'ansible-collections/community.routeros' permissions: contents: write + pages: write + id-token: write needs: [build-docs] name: Publish Ansible Docs uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main with: artifact-name: ${{ needs.build-docs.outputs.artifact-name }} + publish-gh-pages-branch: true secrets: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3c717e40f91e06c92753b841eaee79513ddf558d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Sat, 29 Jun 2024 17:33:08 +0200 Subject: [PATCH 245/365] Add parameter `host-key-type` for `ip ssh` path (#297) Add changelog fragment --- changelogs/fragments/297-add-ip-ssh-host-key-type.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/297-add-ip-ssh-host-key-type.yml diff --git a/changelogs/fragments/297-add-ip-ssh-host-key-type.yml b/changelogs/fragments/297-add-ip-ssh-host-key-type.yml new file mode 100644 index 0000000..96038b1 --- /dev/null +++ b/changelogs/fragments/297-add-ip-ssh-host-key-type.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ac9cf1b..061846f 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3205,6 +3205,9 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.9', '>=')], 'host-key-type', KeyInfo(default='rsa')), + ], fields={ 'allow-none-crypto': KeyInfo(default=False), 'always-allow-password-login': KeyInfo(default=False), From f45c85b818d94d6a0a439fb5191b3c5af5af86bd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 5 Jul 2024 22:33:46 +0200 Subject: [PATCH 246/365] Add link to forum. (#298) --- docs/docsite/links.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docsite/links.yml b/docs/docsite/links.yml index 9da799e..ef9c985 100644 --- a/docs/docsite/links.yml +++ b/docs/docsite/links.yml @@ -25,3 +25,7 @@ communication: mailing_lists: - topic: Ansible Project List url: https://groups.google.com/g/ansible-project + forums: + - topic: Ansible Forum + # The following URL directly points to the "Get Help" section + url: https://forum.ansible.com/c/help/6/none From d7b7f32e161e2c58a694acdb698c038906640d4b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 8 Jul 2024 15:59:21 +0200 Subject: [PATCH 247/365] Update Galaxy description. --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index f978080..0f99196 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -13,7 +13,7 @@ authors: - Egor Zaitsev (github.com/heuels) - Nikolay Dachev (github.com/NikolayDachev) - Felix Fontein (github.com/felixfontein) -description: Modules for MikroTik RouterOS +description: Modules and plugins for MikroTik RouterOS license: - GPL-3.0-or-later #license_file: COPYING From 05de3f2f05ba949dee6c1d09668dc9284bf8ed61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:33:52 +0200 Subject: [PATCH 248/365] Bump fsfe/reuse-action from 3 to 4 (#299) Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 3 to 4. - [Release notes](https://github.com/fsfe/reuse-action/releases) - [Commits](https://github.com/fsfe/reuse-action/compare/v3...v4) --- updated-dependencies: - dependency-name: fsfe/reuse-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/reuse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index b6732cc..7c15c11 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -24,4 +24,4 @@ jobs: - uses: actions/checkout@v4 - name: REUSE Compliance Check - uses: fsfe/reuse-action@v3 + uses: fsfe/reuse-action@v4 From a6361844cda7a1f0cc0489b160a069f478d43fa0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 9 Jul 2024 22:19:52 +0200 Subject: [PATCH 249/365] Prepare 2.17.0. --- changelogs/fragments/2.17.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.17.0.yml diff --git a/changelogs/fragments/2.17.0.yml b/changelogs/fragments/2.17.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/2.17.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index 0f99196..1a455fd 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.16.0 +version: 2.17.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From f1232ee6371456f6134258740fd41292f88ad55c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 9 Jul 2024 22:31:11 +0200 Subject: [PATCH 250/365] Release 2.17.0. --- CHANGELOG.md | 202 ++++++++++-------- CHANGELOG.rst | 15 ++ changelogs/changelog.yaml | 14 ++ changelogs/fragments/2.17.0.yml | 1 - .../294-add-system-health-settings-path.yml | 2 - .../295-add_system_resource_irq_rps_path.yml | 2 - .../297-add-ip-ssh-host-key-type.yml | 2 - 7 files changed, 139 insertions(+), 99 deletions(-) delete mode 100644 changelogs/fragments/2.17.0.yml delete mode 100644 changelogs/fragments/294-add-system-health-settings-path.yml delete mode 100644 changelogs/fragments/295-add_system_resource_irq_rps_path.yml delete mode 100644 changelogs/fragments/297-add-ip-ssh-host-key-type.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index a17b8fc..4e78ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,112 +2,115 @@ **Topics** -- v2\.16\.0 +- v2\.17\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v2\.16\.0 + +## v2\.17\.0 ### Release Summary @@ -117,11 +120,12 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. -* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. +* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. +* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. +* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -131,6 +135,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -145,12 +163,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -160,12 +178,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -179,12 +197,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -198,12 +216,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -218,12 +236,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -255,12 +273,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -274,7 +292,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -295,7 +313,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -308,7 +326,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -321,12 +339,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -346,12 +364,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -364,12 +382,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -384,12 +402,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -402,12 +420,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -446,7 +464,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -459,12 +477,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -479,7 +497,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -493,12 +511,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -517,12 +535,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -546,12 +564,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -587,12 +605,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -608,12 +626,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -622,7 +640,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -635,7 +653,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -648,7 +666,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -661,12 +679,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1a735af..011644d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,21 @@ Community RouterOS Release Notes .. contents:: Topics +v2.17.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). +- api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). +- api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). + v2.16.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 71044fb..43ac640 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -382,6 +382,20 @@ releases: - 286-add_ppp_secret_path.yml - 288-interface_ethernet_values.yml release_date: '2024-06-16' + 2.17.0: + changes: + minor_changes: + - api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). + - api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). + - api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path + (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). + release_summary: Feature release. + fragments: + - 2.17.0.yml + - 294-add-system-health-settings-path.yml + - 295-add_system_resource_irq_rps_path.yml + - 297-add-ip-ssh-host-key-type.yml + release_date: '2024-07-09' 2.2.0: changes: bugfixes: diff --git a/changelogs/fragments/2.17.0.yml b/changelogs/fragments/2.17.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/2.17.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/294-add-system-health-settings-path.yml b/changelogs/fragments/294-add-system-health-settings-path.yml deleted file mode 100644 index 13d38b4..0000000 --- a/changelogs/fragments/294-add-system-health-settings-path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). diff --git a/changelogs/fragments/295-add_system_resource_irq_rps_path.yml b/changelogs/fragments/295-add_system_resource_irq_rps_path.yml deleted file mode 100644 index 0ebacd0..0000000 --- a/changelogs/fragments/295-add_system_resource_irq_rps_path.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). \ No newline at end of file diff --git a/changelogs/fragments/297-add-ip-ssh-host-key-type.yml b/changelogs/fragments/297-add-ip-ssh-host-key-type.yml deleted file mode 100644 index 96038b1..0000000 --- a/changelogs/fragments/297-add-ip-ssh-host-key-type.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). From 971145b28431a4391214dda3e50b0850088ace1e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 11 Jul 2024 22:44:30 +0200 Subject: [PATCH 251/365] Reformat and re-order changelogs/changelog.yaml. --- changelogs/changelog.yaml | 1063 +++++++++++++++++++------------------ changelogs/config.yaml | 38 +- 2 files changed, 555 insertions(+), 546 deletions(-) diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 43ac640..26cde43 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -1,666 +1,463 @@ +--- ancestor: null releases: 0.1.0: changes: minor_changes: - - facts - now also collecting data about BGP and OSPF (https://github.com/ansible-collections/community.network/pull/101). - - facts - set configuration export on to verbose, for full configuration export - (https://github.com/ansible-collections/community.network/pull/104). + - facts - now also collecting data about BGP and OSPF (https://github.com/ansible-collections/community.network/pull/101). + - facts - set configuration export on to verbose, for full configuration export + (https://github.com/ansible-collections/community.network/pull/104). release_summary: 'The ``community.routeros`` continues the work on the Ansible RouterOS modules from their state in ``community.network`` 1.2.0. The changes listed here are thus relative to the modules ``community.network.routeros_*``. ' fragments: - - 0.1.0.yml - - 101_update_facts.yml - - 104_facts_export_verbose.yml + - 0.1.0.yml + - 101_update_facts.yml + - 104_facts_export_verbose.yml release_date: '2020-10-26' 0.1.1: changes: bugfixes: - - api - fix crash when the ``ssl`` parameter is used (https://github.com/ansible-collections/community.routeros/pull/3). + - api - fix crash when the ``ssl`` parameter is used (https://github.com/ansible-collections/community.routeros/pull/3). release_summary: Small improvements and bugfixes over the initial release. fragments: - - 0.1.1.yml - - 3-api-ssl.yml + - 0.1.1.yml + - 3-api-ssl.yml release_date: '2020-10-31' 1.0.0: changes: bugfixes: - - routeros terminal plugin - allow slashes in hostnames for terminal detection. - Without this, slashes in hostnames will result in connection timeouts (https://github.com/ansible-collections/community.network/pull/138). + - routeros terminal plugin - allow slashes in hostnames for terminal detection. + Without this, slashes in hostnames will result in connection timeouts (https://github.com/ansible-collections/community.network/pull/138). release_summary: 'This is the first production (non-prerelease) release of ``community.routeros``. ' fragments: - - 1.0.0.yml - - community.network-138-routeros-allow-slash.yml + - 1.0.0.yml + - community.network-138-routeros-allow-slash.yml release_date: '2020-11-17' 1.0.1: changes: bugfixes: - - api - remove ``id to .id`` as default requirement which conflicts with RouterOS - ``id`` configuration parameter (https://github.com/ansible-collections/community.routeros/pull/15). + - api - remove ``id to .id`` as default requirement which conflicts with RouterOS + ``id`` configuration parameter (https://github.com/ansible-collections/community.routeros/pull/15). release_summary: Maintenance release with a bugfix for ``api``. fragments: - - 1.0.1.yml - - 13-remove-id-restriction-for-api.yaml + - 1.0.1.yml + - 13-remove-id-restriction-for-api.yaml release_date: '2020-12-11' 1.1.0: changes: minor_changes: - - command - added support for a dash (``-``) in username (https://github.com/ansible-collections/community.routeros/pull/18). - - facts - added support for a dash (``-``) in username (https://github.com/ansible-collections/community.routeros/pull/18). + - command - added support for a dash (``-``) in username (https://github.com/ansible-collections/community.routeros/pull/18). + - facts - added support for a dash (``-``) in username (https://github.com/ansible-collections/community.routeros/pull/18). release_summary: This release allow dashes in usernames for SSH-based modules. fragments: - - 1.1.0.yml - - 18-support-dashes-in-username.yml + - 1.1.0.yml + - 18-support-dashes-in-username.yml release_date: '2021-01-04' 1.2.0: changes: bugfixes: - - api - when using TLS/SSL, remove explicit cipher configuration to insecure - values, which also makes it impossible to connect to newer RouterOS versions - (https://github.com/ansible-collections/community.routeros/pull/34). + - api - when using TLS/SSL, remove explicit cipher configuration to insecure + values, which also makes it impossible to connect to newer RouterOS versions + (https://github.com/ansible-collections/community.routeros/pull/34). minor_changes: - - Avoid internal ansible-core module_utils in favor of equivalent public API - available since at least Ansible 2.9 (https://github.com/ansible-collections/community.routeros/pull/38). - - api - add options ``validate_certs`` (default value ``true``), ``validate_cert_hostname`` - (default value ``false``), and ``ca_path`` to control certificate validation - (https://github.com/ansible-collections/community.routeros/pull/37). - - api - rename option ``ssl`` to ``tls``, and keep the old name as an alias - (https://github.com/ansible-collections/community.routeros/pull/37). - - fact - add fact ``ansible_net_config_nonverbose`` to get idempotent config - (no date, no verbose) (https://github.com/ansible-collections/community.routeros/pull/23). + - Avoid internal ansible-core module_utils in favor of equivalent public API + available since at least Ansible 2.9 (https://github.com/ansible-collections/community.routeros/pull/38). + - api - add options ``validate_certs`` (default value ``true``), ``validate_cert_hostname`` + (default value ``false``), and ``ca_path`` to control certificate validation + (https://github.com/ansible-collections/community.routeros/pull/37). + - api - rename option ``ssl`` to ``tls``, and keep the old name as an alias + (https://github.com/ansible-collections/community.routeros/pull/37). + - fact - add fact ``ansible_net_config_nonverbose`` to get idempotent config + (no date, no verbose) (https://github.com/ansible-collections/community.routeros/pull/23). release_summary: Bugfix and feature release. fragments: - - 1.2.0.yml - - 23-idempotent_config.yml - - 34-api-ciphers.yml - - 37-api-validate-cert-options.yml - - ansible-core-_text.yml + - 1.2.0.yml + - 23-idempotent_config.yml + - 34-api-ciphers.yml + - 37-api-validate-cert-options.yml + - ansible-core-_text.yml release_date: '2021-06-29' - 2.0.0: - changes: - minor_changes: - - command - the ``commands`` and ``wait_for`` options now convert the list elements - to strings (https://github.com/ansible-collections/community.routeros/pull/55). - - facts - the ``gather_subset`` option now converts the list elements to strings - (https://github.com/ansible-collections/community.routeros/pull/55). - release_summary: A new major release with breaking changes in the behavior of - ``community.routeros.api`` and ``community.routeros.command``. - fragments: - - 2.0.0.yml - - 55-linting.yml - release_date: '2021-10-31' 2.0.0-a1: changes: breaking_changes: - - 'api - due to a programming error, the module never failed on errors. This - has now been fixed. If you are relying on the module not failing in case of - idempotent commands (resulting in errors like ``failure: already have such - address``), you need to adjust your roles/playbooks. We suggest to use ``failed_when`` - to accept failure in specific circumstances, for example ``failed_when: "''failure: - already have '' in result.msg[0]"`` (https://github.com/ansible-collections/community.routeros/pull/39).' + - 'api - due to a programming error, the module never failed on errors. This + has now been fixed. If you are relying on the module not failing in case + of idempotent commands (resulting in errors like ``failure: already have + such address``), you need to adjust your roles/playbooks. We suggest to + use ``failed_when`` to accept failure in specific circumstances, for example + ``failed_when: "''failure: already have '' in result.msg[0]"`` (https://github.com/ansible-collections/community.routeros/pull/39).' release_summary: First prerelease for a new major release with a breaking change in the behavior of ``community.routeros.api``. fragments: - - 2.0.0-a1.yml - - 39-api-fail.yml + - 2.0.0-a1.yml + - 39-api-fail.yml release_date: '2021-07-31' 2.0.0-a2: changes: breaking_changes: - - api - splitting commands no longer uses a naive split by whitespace, but a - more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45). - - command - the module now always indicates that a change happens. If this is - not correct, please use ``changed_when`` to determine the correct changed - status for a task (https://github.com/ansible-collections/community.routeros/pull/50). + - api - splitting commands no longer uses a naive split by whitespace, but + a more RouterOS CLI compatible splitting algorithm (https://github.com/ansible-collections/community.routeros/pull/45). + - command - the module now always indicates that a change happens. If this + is not correct, please use ``changed_when`` to determine the correct changed + status for a task (https://github.com/ansible-collections/community.routeros/pull/50). bugfixes: - - api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47). - - api - when converting result lists to dictionaries, no longer removes second - ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47). - - routeros cliconf plugin - adjust function signature that was modified in Ansible - after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43). + - api - improve splitting of ``WHERE`` queries (https://github.com/ansible-collections/community.routeros/pull/47). + - api - when converting result lists to dictionaries, no longer removes second + ``=`` and text following that if present (https://github.com/ansible-collections/community.routeros/pull/47). + - routeros cliconf plugin - adjust function signature that was modified in + Ansible after creation of this plugin (https://github.com/ansible-collections/community.routeros/pull/43). minor_changes: - - api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53). + - api - make validation of ``WHERE`` for ``query`` more strict (https://github.com/ansible-collections/community.routeros/pull/53). release_summary: Second prerelease for a new major release with breaking changes in the behavior of ``community.routeros.api`` and ``community.routeros.command``. fragments: - - 2.0.0-a2.yml - - 43-sanity.yml - - 45-api-split.yml - - 47-api-split.yml - - 50-command-changed.yml - - 53-api-where.yml - - 53-quoting-filters.yml + - 2.0.0-a2.yml + - 43-sanity.yml + - 45-api-split.yml + - 47-api-split.yml + - 50-command-changed.yml + - 53-api-where.yml + - 53-quoting-filters.yml plugins: filter: - - description: Join a list of arguments to a command - name: join - namespace: null - - description: Convert a list of arguments to a list of dictionary - name: list_to_dict - namespace: null - - description: Quote an argument - name: quote_argument - namespace: null - - description: Quote an argument value - name: quote_argument_value - namespace: null - - description: Split a command into arguments - name: split - namespace: null + - description: Join a list of arguments to a command + name: join + namespace: null + - description: Convert a list of arguments to a list of dictionary + name: list_to_dict + namespace: null + - description: Quote an argument + name: quote_argument + namespace: null + - description: Quote an argument value + name: quote_argument_value + namespace: null + - description: Split a command into arguments + name: split + namespace: null release_date: '2021-10-14' + 2.0.0: + changes: + minor_changes: + - command - the ``commands`` and ``wait_for`` options now convert the list + elements to strings (https://github.com/ansible-collections/community.routeros/pull/55). + - facts - the ``gather_subset`` option now converts the list elements to strings + (https://github.com/ansible-collections/community.routeros/pull/55). + release_summary: A new major release with breaking changes in the behavior of + ``community.routeros.api`` and ``community.routeros.command``. + fragments: + - 2.0.0.yml + - 55-linting.yml + release_date: '2021-10-31' 2.1.0: changes: bugfixes: - - query - fix query function check for ``.id`` vs. ``id`` arguments to not conflict - with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, - https://github.com/ansible-collections/community.routeros/issues/67). - - quoting and unquoting filter plugins, api module - handle the escape sequence - ``\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89). + - query - fix query function check for ``.id`` vs. ``id`` arguments to not + conflict with routeros arguments like ``identity`` (https://github.com/ansible-collections/community.routeros/pull/68, + https://github.com/ansible-collections/community.routeros/issues/67). + - quoting and unquoting filter plugins, api module - handle the escape sequence + ``\_`` correctly as escaping a space and not an underscore (https://github.com/ansible-collections/community.routeros/pull/89). minor_changes: - - Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` - to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89). - - Prepare collection for inclusion in an Execution Environment by declaring - its dependencies (https://github.com/ansible-collections/community.routeros/pull/83). - - api - add new option ``extended query`` more complex queries against RouterOS - API (https://github.com/ansible-collections/community.routeros/pull/63). - - api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63). - - api* modules - allow to set an encoding other than the default ASCII for communicating - with the API (https://github.com/ansible-collections/community.routeros/pull/95). + - Added a ``community.routeros.api`` module defaults group. Use with ``group/community.routeros.api`` + to provide options for all API-based modules (https://github.com/ansible-collections/community.routeros/pull/89). + - Prepare collection for inclusion in an Execution Environment by declaring + its dependencies (https://github.com/ansible-collections/community.routeros/pull/83). + - api - add new option ``extended query`` more complex queries against RouterOS + API (https://github.com/ansible-collections/community.routeros/pull/63). + - api - update ``query`` to accept symbolic parameters (https://github.com/ansible-collections/community.routeros/pull/63). + - api* modules - allow to set an encoding other than the default ASCII for + communicating with the API (https://github.com/ansible-collections/community.routeros/pull/95). release_summary: Feature and bugfix release with new modules. fragments: - - 2.1.0.yml - - 63-add-extended_query.yml - - 68-fix-query-id-check.yml - - 83-ee.yml - - 89-quoting.yml - - 90-api-action-group.yml - - 95-api-encoding.yml + - 2.1.0.yml + - 63-add-extended_query.yml + - 68-fix-query-id-check.yml + - 83-ee.yml + - 89-quoting.yml + - 90-api-action-group.yml + - 95-api-encoding.yml modules: - - description: Collect facts from remote devices running MikroTik RouterOS using - the API - name: api_facts - namespace: '' - - description: Find and modify information using the API - name: api_find_and_modify - namespace: '' + - description: Collect facts from remote devices running MikroTik RouterOS using + the API + name: api_facts + namespace: '' + - description: Find and modify information using the API + name: api_find_and_modify + namespace: '' release_date: '2022-05-25' - 2.10.0: - changes: - bugfixes: - - api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` - is only available on RouterOS 7.10+, and that ``engine-id`` is read-only on - RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, - https://github.com/ansible-collections/community.routeros/pull/218). - minor_changes: - - api_info - add new ``include_read_only`` option to select behavior for read-only - values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213). - - api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` - introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). - - api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` - under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). - - api_info, api_modify - add support for the ``interface ppp-client`` path (https://github.com/ansible-collections/community.routeros/pull/199). - - api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). - - api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). - - api_info, api_modify - add support for the ``ip dhcp-server option`` and ``ip - dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). - - api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool - graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). - - api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). - - api_info, api_modify - add support for the ``mode`` property in ``ip neighbor - discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). - - api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). - - api_info, api_modify - add support for the ``routing filter rule`` and ``routing - filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). - - api_info, api_modify - add support for the ``routing table`` path in RouterOS - 7 (https://github.com/ansible-collections/community.routeros/pull/215). - - api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS - 7 (https://github.com/ansible-collections/community.routeros/pull/216). - - api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). - - api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). - - api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` - path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). - - api_info, api_modify - finalize fields for the ``ppp profile`` path and enable - it (https://github.com/ansible-collections/community.routeros/pull/217). - - api_modify - add new ``handle_read_only`` and ``handle_write_only`` options - to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213). - - api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` - (https://github.com/ansible-collections/community.routeros/pull/220). - release_summary: Bugfix and feature release. - fragments: - - 195-add-interface-wireless-data.yml - - 197-dns-static-addrlist-matchsubdomain.yml - - 198-ip-nd-mode.yml - - 199-add-interface-pppclient.yml - - 2.10.0.yml - - 200-add-routing-filter.yml - - 201-add-user-settings.yml - - 203-wireless-security-profiles.yml - - 204-add-ipv6-firewall-nat.yml - - 205-add-iot-modbus.yml - - 210-date-time-gmt-offset.yml - - 211-user.yml - - 213-read-write-only.yml - - 215-add-routing-table.yml - - 216-add-tool-netwatch.yml - - 217-ppp-profiles.yml - - 218-snmp-engine-id.yml - - 220-routing-id-bgp-connection.yml - - 223-add-ip-dhcp-server-option.yml - - 224-add-port-remote-access.yml - - 227-add-upnp-graphing.yml - release_date: '2023-10-08' - 2.11.0: - changes: - minor_changes: - - api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, - ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path - (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) - - api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, - ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path - (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). - - api_info, api_modify - mark the ``interface wireless`` parameter ``running`` - as read-only (https://github.com/ansible-collections/community.routeros/pull/233). - - api_info, api_modify - set the default value to ``false`` for the ``disabled`` - parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). - - api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - add missing attributes to the ``routing bgp connection`` path - (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 release) - (https://github.com/ansible-collections/community.routeros/pull/234). - - api_modify - make ``/ip traffic-flow target`` a multiple value attribute (https://github.com/ansible-collections/community.routeros/pull/234). - release_summary: Feature and bugfix release. - fragments: - - 2.11.0.yml - - 233-wireless-running-read-only.yml - - 234-bugfixes-and-update-adaptations.yml - - 235-add-missing-dns-attributes.yml - - 237-add-missing-ip-firewall-attributes.yml - release_date: '2023-12-03' - 2.12.0: - changes: - minor_changes: - - api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, - https://github.com/ansible-collections/community.routeros/pull/244). - - api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, - https://github.com/ansible-collections/community.routeros/pull/245). - - api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, - https://github.com/ansible-collections/community.routeros/pull/246). - - api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). - - api_info, api_modify - add support for the ``tx-power`` attribute in ``interface - wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). - - api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` path - (https://github.com/ansible-collections/community.routeros/pull/248). - - api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). - release_summary: Feature release. - fragments: - - 2.12.0.yml - - 226-support-for-WifiWave2.yml - - 239-wireless-tx-power.yml - - 243-add-routing-bgp-template-path.yml - - 244-add-interface-ovpn-client-path.yml - - 245-add-radius-path.yml - - 246-add-routing-rule-path.yml - - 247-removed-primary-key-host-in-tool-netwatch.yml - release_date: '2024-01-21' - 2.13.0: - changes: - bugfixes: - - facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). - minor_changes: - - api_info, api_modify - make path ``user group`` modifiable and add ``comment`` - attribute (https://github.com/ansible-collections/community.routeros/issues/256, - https://github.com/ansible-collections/community.routeros/pull/257). - - api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) - release_summary: Bugfix and feature release. - fragments: - - 2.13.0.yml - - 257-make-user_group-modifiable.yml - - 259-add-routeros7-support-for-ip-vrf.yml - - 262-fix-date-removal.yml - release_date: '2024-02-25' - 2.14.0: - changes: - minor_changes: - - api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` - and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). - - api_info, api_modify - added support for ``interface wifi`` and its sub-paths - (https://github.com/ansible-collections/community.routeros/pull/266). - - api_info, api_modify - remove default value for read-only ``running`` field - in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). - release_summary: Feature release. - fragments: - - 2.14.0.yml - - 263-sys-pkg-update.yml - - 264-wireless-running-default.yml - - 266-interface-wifi.yml - release_date: '2024-03-25' - 2.15.0: - changes: - minor_changes: - - api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). - - api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). - - api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). - - api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 - address`` (https://github.com/ansible-collections/community.routeros/pull/270). - - api_info, api_modify - add missing path ``/interface pppoe-server server`` - (https://github.com/ansible-collections/community.routeros/pull/273). - - api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). - - api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). - - api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). - - api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing - bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). - - api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls - ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` - (https://github.com/ansible-collections/community.routeros/pull/272). - release_summary: Feature release. - fragments: - - 2.15.0.yml - - 269-add-queue_simple-path.yml - - 270_fix_ipv6_from_pool_default_value.yml - - 271-mpls_ldp_routeros_7_support.yml - - 272-additional_mpls_path_support.yml - - 273-add_interface_pppoe-server_support.yml - - 274-add_queue_type_path.yml - - 276-add_ip_dhcp-relay_path.yml - - 277-add_routing_bgp_paths.yml - - 278-add_ip_route_rule_path.yml - - 279-add_routing_filter_path.yml - release_date: '2024-04-20' - 2.16.0: - changes: - minor_changes: - - api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). - - api_info, api_modify - minor changes ``/interface ethernet`` path fields (https://github.com/ansible-collections/community.routeros/pull/288). - release_summary: Feature release. - fragments: - - 2.16.0.yml - - 286-add_ppp_secret_path.yml - - 288-interface_ethernet_values.yml - release_date: '2024-06-16' - 2.17.0: - changes: - minor_changes: - - api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). - - api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). - - api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path - (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). - release_summary: Feature release. - fragments: - - 2.17.0.yml - - 294-add-system-health-settings-path.yml - - 295-add_system_resource_irq_rps_path.yml - - 297-add-ip-ssh-host-key-type.yml - release_date: '2024-07-09' 2.2.0: changes: bugfixes: - - Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils - (https://github.com/ansible-collections/community.routeros/pull/101). + - Include ``LICENSES/BSD-2-Clause.txt`` file for the ``routeros`` module utils + (https://github.com/ansible-collections/community.routeros/pull/101). minor_changes: - - All software licenses are now in the ``LICENSES/`` directory of the collection - root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable - license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101). + - All software licenses are now in the ``LICENSES/`` directory of the collection + root. Moreover, ``SPDX-License-Identifier:`` is used to declare the applicable + license for every file that is not automatically generated (https://github.com/ansible-collections/community.routeros/pull/101). release_summary: New feature release. fragments: - - 101-licenses.yml - - 2.2.0.yml + - 101-licenses.yml + - 2.2.0.yml modules: - - description: Retrieve information from API - name: api_info - namespace: '' - - description: Modify data at paths with API - name: api_modify - namespace: '' + - description: Retrieve information from API + name: api_info + namespace: '' + - description: Modify data at paths with API + name: api_modify + namespace: '' release_date: '2022-07-31' 2.2.1: changes: bugfixes: - - api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` - (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107). - - api_modify, api_info - make API path ``ip dhcp-server network`` support missing - options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, - and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, - https://github.com/ansible-collections/community.routeros/pull/106). + - api_modify, api_info - make API path ``ip dhcp-server lease`` support ``server=all`` + (https://github.com/ansible-collections/community.routeros/issues/104, https://github.com/ansible-collections/community.routeros/pull/107). + - api_modify, api_info - make API path ``ip dhcp-server network`` support + missing options ``boot-file-name``, ``dhcp-option-set``, ``dns-none``, ``domain``, + and ``next-server`` (https://github.com/ansible-collections/community.routeros/issues/104, + https://github.com/ansible-collections/community.routeros/pull/106). release_summary: Bugfix release. fragments: - - 106-api-path-ip-dhcp-network.yml - - 107-api-path-ip-dhcp-lease.yml - - 2.2.1.yml + - 106-api-path-ip-dhcp-network.yml + - 107-api-path-ip-dhcp-lease.yml + - 2.2.1.yml release_date: '2022-08-20' 2.3.0: changes: bugfixes: - - api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, - and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` - (https://github.com/ansible-collections/community.routeros/pull/110). + - api_modify, api_info - make API path ``ip dhcp-server`` support ``script``, + and ``ip firewall nat`` support ``in-interface`` and ``in-interface-list`` + (https://github.com/ansible-collections/community.routeros/pull/110). minor_changes: - - The collection repository conforms to the `REUSE specification `__ - except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108). - - api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109). - - api_modify, api_info - support API path ``ip firewall mangle`` (https://github.com/ansible-collections/community.routeros/pull/110). + - The collection repository conforms to the `REUSE specification `__ + except for the changelog fragments (https://github.com/ansible-collections/community.routeros/pull/108). + - api* modules - added ``timeout`` parameter (https://github.com/ansible-collections/community.routeros/pull/109). + - api_modify, api_info - support API path ``ip firewall mangle`` (https://github.com/ansible-collections/community.routeros/pull/110). release_summary: Feature and bugfix release. fragments: - - 109-add-timeout-parameter-to-api.yml - - 110-api.yml - - 2.3.0.yml - - licenses.yml + - 109-add-timeout-parameter-to-api.yml + - 110-api.yml + - 2.3.0.yml + - licenses.yml release_date: '2022-09-11' 2.3.1: changes: known_issues: - - The ``community.routeros.command`` module claims to support check mode. Since - it cannot judge whether the commands executed modify state or not, this behavior - is incorrect. Since this potentially breaks existing playbooks, we will not - change this behavior until community.routeros 3.0.0. + - The ``community.routeros.command`` module claims to support check mode. + Since it cannot judge whether the commands executed modify state or not, + this behavior is incorrect. Since this potentially breaks existing playbooks, + we will not change this behavior until community.routeros 3.0.0. release_summary: Maintenance release with improved documentation. fragments: - - 2.3.1.yml - - command-check_mode.yml + - 2.3.1.yml + - command-check_mode.yml release_date: '2022-11-06' 2.4.0: changes: bugfixes: - - api_modify - ``ip route`` entry can be defined without the need of ``gateway`` - field, which is correct for unreachable/blackhole type of routes (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify - ``queue interface`` path works now (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 - firewall address-list`` (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - the default of the field ``ingress-filtering`` in ``interface - bridge port`` is now ``true``, which is the default in ROS (https://github.com/ansible-collections/community.routeros/pull/125). - - command, facts - commands do not timeout in safe mode anymore (https://github.com/ansible-collections/community.routeros/pull/134). + - api_modify - ``ip route`` entry can be defined without the need of ``gateway`` + field, which is correct for unreachable/blackhole type of routes (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify - ``queue interface`` path works now (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - removed wrong field ``dynamic`` from API path ``ipv6 + firewall address-list`` (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - the default of the field ``ingress-filtering`` in + ``interface bridge port`` is now ``true``, which is the default in ROS (https://github.com/ansible-collections/community.routeros/pull/125). + - command, facts - commands do not timeout in safe mode anymore (https://github.com/ansible-collections/community.routeros/pull/134). known_issues: - - api_modify - when limits for entries in ``queue tree`` are defined as human - readable - for example ``25M`` -, the configuration will be correctly set - in ROS, but the module will indicate the item is changed on every run even - when there was no change done. This is caused by the ROS API which returns - the number in bytes - for example ``25000000`` (which is inconsistent with - the CLI behavior). In order to mitigate that, the limits have to be defined - in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, - ``routing ospf instance``, ``routing ospf interface-template`` paths are not - fully implemented for ROS6 due to the significant changes between ROS6 and - ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify - when limits for entries in ``queue tree`` are defined as human + readable - for example ``25M`` -, the configuration will be correctly set + in ROS, but the module will indicate the item is changed on every run even + when there was no change done. This is caused by the ROS API which returns + the number in bytes - for example ``25000000`` (which is inconsistent with + the CLI behavior). In order to mitigate that, the limits have to be defined + in bytes (those will still appear as human readable in the ROS CLI) (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, + ``routing ospf instance``, ``routing ospf interface-template`` paths are + not fully implemented for ROS6 due to the significant changes between ROS6 + and ROS7 (https://github.com/ansible-collections/community.routeros/pull/131). minor_changes: - - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers - (https://github.com/ansible-collections/community.routeros/pull/124). - - api_info - new parameter ``include_builtin`` which allows to include "builtin" - entries that are automatically generated by ROS and cannot be modified by - the user (https://github.com/ansible-collections/community.routeros/pull/130). - - api_modify, api_info - support API paths - ``interface bonding``, ``interface - bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, - ``system script``, ``system ups`` (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man - configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man provisioning``, - ``caps-man security`` (https://github.com/ansible-collections/community.routeros/pull/126). - - api_modify, api_info - support API paths ``interface list`` and ``interface - list member`` (https://github.com/ansible-collections/community.routeros/pull/120). - - api_modify, api_info - support API paths ``interface pppoe-client``, ``interface - vlan``, ``interface bridge``, ``interface bridge vlan`` (https://github.com/ansible-collections/community.routeros/pull/125). - - api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec - peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` (https://github.com/ansible-collections/community.routeros/pull/129). - - api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` - (https://github.com/ansible-collections/community.routeros/pull/123). - - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, - ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf - area``, ``routing ospf area range``, ``routing ospf instance``, ``routing - ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` - (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify, api_info - support API paths ``system logging``, ``system logging - action`` (https://github.com/ansible-collections/community.routeros/pull/127). - - api_modify, api_info - support field ``hw-offload`` for path ``ip firewall - filter`` (https://github.com/ansible-collections/community.routeros/pull/121). - - api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, - ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, - ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, - ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, - ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, - ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, - ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, ``packet-mark``, - ``packet-size``, ``per-connection-classifier``, ``port``, ``priority``, ``psd``, - ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, ``src-address``, - ``src-address-list``, ``src-address-type``, ``src-mac-address``, ``src-port``, - ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, - ``mdix-enable``, ``poe-out``, ``poe-priority``, ``poe-voltage``, ``power-cycle-interval``, - ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` - for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). - - api_modify, api_info - support fields ``jump-target``, ``reject-with`` in - ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` - API path, field ``jump-target`` in ``ip firewall mangle`` API path, field - ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, - ``reject-with`` in ``ipv6 firewall filter`` API path (https://github.com/ansible-collections/community.routeros/pull/133). - - api_modify, api_info - support for API fields that can be disabled and have - default value at the same time, support API paths ``interface gre``, ``interface - eoip`` (https://github.com/ansible-collections/community.routeros/pull/128). - - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, - ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path - (https://github.com/ansible-collections/community.routeros/pull/131). - - api_modify, api_info - support paths ``system ntp client servers`` and ``system - ntp server`` available in ROS7, as well as new fields ``servers``, ``mode``, - and ``vrf`` for ``system ntp client`` (https://github.com/ansible-collections/community.routeros/pull/122). + - api* modules - Add new option ``force_no_cert`` to connect with ADH ciphers + (https://github.com/ansible-collections/community.routeros/pull/124). + - api_info - new parameter ``include_builtin`` which allows to include "builtin" + entries that are automatically generated by ROS and cannot be modified by + the user (https://github.com/ansible-collections/community.routeros/pull/130). + - api_modify, api_info - support API paths - ``interface bonding``, ``interface + bridge mlag``, ``ipv6 firewall mangle``, ``ipv6 nd``, ``system scheduler``, + ``system script``, ``system ups`` (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support API paths ``caps-man access-list``, ``caps-man + configuration``, ``caps-man datapath``, ``caps-man manager``, ``caps-man + provisioning``, ``caps-man security`` (https://github.com/ansible-collections/community.routeros/pull/126). + - api_modify, api_info - support API paths ``interface list`` and ``interface + list member`` (https://github.com/ansible-collections/community.routeros/pull/120). + - api_modify, api_info - support API paths ``interface pppoe-client``, ``interface + vlan``, ``interface bridge``, ``interface bridge vlan`` (https://github.com/ansible-collections/community.routeros/pull/125). + - api_modify, api_info - support API paths ``ip ipsec identity``, ``ip ipsec + peer``, ``ip ipsec policy``, ``ip ipsec profile``, ``ip ipsec proposal`` + (https://github.com/ansible-collections/community.routeros/pull/129). + - api_modify, api_info - support API paths ``ip route`` and ``ip route vrf`` + (https://github.com/ansible-collections/community.routeros/pull/123). + - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, + ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf + area``, ``routing ospf area range``, ``routing ospf instance``, ``routing + ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` + (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - support API paths ``system logging``, ``system logging + action`` (https://github.com/ansible-collections/community.routeros/pull/127). + - api_modify, api_info - support field ``hw-offload`` for path ``ip firewall + filter`` (https://github.com/ansible-collections/community.routeros/pull/121). + - api_modify, api_info - support fields ``address-list``, ``address-list-timeout``, + ``connection-bytes``, ``connection-limit``, ``connection-mark``, ``connection-rate``, + ``connection-type``, ``content``, ``disabled``, ``dscp``, ``dst-address-list``, + ``dst-address-type``, ``dst-limit``, ``fragment``, ``hotspot``, ``icmp-options``, + ``in-bridge-port``, ``in-bridge-port-list``, ``ingress-priority``, ``ipsec-policy``, + ``ipv4-options``, ``jump-target``, ``layer7-protocol``, ``limit``, ``log``, + ``log-prefix``, ``nth``, ``out-bridge-port``, ``out-bridge-port-list``, + ``packet-mark``, ``packet-size``, ``per-connection-classifier``, ``port``, + ``priority``, ``psd``, ``random``, ``realm``, ``routing-mark``, ``same-not-by-dst``, + ``src-address``, ``src-address-list``, ``src-address-type``, ``src-mac-address``, + ``src-port``, ``tcp-mss``, ``time``, ``tls-host``, ``ttl`` in ``ip firewall + nat`` path (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support fields ``combo-mode``, ``comment``, ``fec-mode``, + ``mdix-enable``, ``poe-out``, ``poe-priority``, ``poe-voltage``, ``power-cycle-interval``, + ``power-cycle-ping-address``, ``power-cycle-ping-enabled``, ``power-cycle-ping-timeout`` + for path ``interface ethernet`` (https://github.com/ansible-collections/community.routeros/pull/121). + - api_modify, api_info - support fields ``jump-target``, ``reject-with`` in + ``ip firewall filter`` API path, field ``comment`` in ``ip firwall address-list`` + API path, field ``jump-target`` in ``ip firewall mangle`` API path, field + ``comment`` in ``ipv6 firewall address-list`` API path, fields ``jump-target``, + ``reject-with`` in ``ipv6 firewall filter`` API path (https://github.com/ansible-collections/community.routeros/pull/133). + - api_modify, api_info - support for API fields that can be disabled and have + default value at the same time, support API paths ``interface gre``, ``interface + eoip`` (https://github.com/ansible-collections/community.routeros/pull/128). + - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, + ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path + (https://github.com/ansible-collections/community.routeros/pull/131). + - api_modify, api_info - support paths ``system ntp client servers`` and ``system + ntp server`` available in ROS7, as well as new fields ``servers``, ``mode``, + and ``vrf`` for ``system ntp client`` (https://github.com/ansible-collections/community.routeros/pull/122). release_summary: Feature release improving the ``api*`` modules. fragments: - - 120-api.yml - - 121-api.yml - - 122-api.yml - - 123-api.yml - - 124-api.yml - - 125-api.yml - - 126-api-capsman.yml - - 127-logging.yml - - 128-api.yml - - 129-api-ipsec.yml - - 130-api-modify-builtin.yml - - 131-api.yml - - 133-api.yml - - 134-command-safemode.yml - - 2.4.0.yml + - 120-api.yml + - 121-api.yml + - 122-api.yml + - 123-api.yml + - 124-api.yml + - 125-api.yml + - 126-api-capsman.yml + - 127-logging.yml + - 128-api.yml + - 129-api-ipsec.yml + - 130-api-modify-builtin.yml + - 131-api.yml + - 133-api.yml + - 134-command-safemode.yml + - 2.4.0.yml release_date: '2022-11-18' 2.5.0: changes: bugfixes: - - api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` - is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). + - api_modify - ``address-pool`` field of entries in API path ``ip dhcp-server`` + is not required anymore (https://github.com/ansible-collections/community.routeros/pull/137). minor_changes: - - api_info, api_modify - support API paths ``interface ethernet poe``, ``interface - gre6``, ``interface vrrp`` and also support all previously missing fields - of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). + - api_info, api_modify - support API paths ``interface ethernet poe``, ``interface + gre6``, ``interface vrrp`` and also support all previously missing fields + of entries in ``ip dhcp-server`` (https://github.com/ansible-collections/community.routeros/pull/137). release_summary: Feature and bugfix release. fragments: - - 137-api.yml - - 2.5.0.yml + - 137-api.yml + - 2.5.0.yml release_date: '2022-12-04' 2.6.0: changes: bugfixes: - - api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). - - api_modify, api_info - do not crash if router contains ``regexp`` DNS entries - in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify - do not use ``name`` as a unique key in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify, api_info - do not crash if router contains ``regexp`` DNS entries + in ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). minor_changes: - - api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). - - api_modify, api_info - support API paths ``interface wireguard``, ``interface - wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). + - api_modify, api_info - add field ``regexp`` to ``ip dns static`` (https://github.com/ansible-collections/community.routeros/issues/141). + - api_modify, api_info - support API paths ``interface wireguard``, ``interface + wireguard peers`` (https://github.com/ansible-collections/community.routeros/pull/143). release_summary: Regular bugfix and feature release. fragments: - - 142-dns-regexp.yml - - 143-add-wireguard.yml - - 2.6.0.yml + - 142-dns-regexp.yml + - 143-add-wireguard.yml + - 2.6.0.yml release_date: '2023-01-01' 2.7.0: changes: bugfixes: - - api_modify, api_info - defaults corrected for fields in ``interface wireguard - peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). + - api_modify, api_info - defaults corrected for fields in ``interface wireguard + peers`` API path (https://github.com/ansible-collections/community.routeros/pull/144). minor_changes: - - api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, - ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). + - api_modify, api_info - support API paths ``ip arp``, ``ip firewall raw``, + ``ipv6 firewall raw`` (https://github.com/ansible-collections/community.routeros/pull/144). release_summary: Bugfix and feature release. fragments: - - 144-paths.yml - - 2.7.0.yml + - 144-paths.yml + - 2.7.0.yml release_date: '2023-01-14' 2.8.0: changes: bugfixes: - - api_info, api_modify - fix default and remove behavior for ``dhcp-options`` - in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, - https://github.com/ansible-collections/community.routeros/pull/154). - - api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154). - - various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149). + - api_info, api_modify - fix default and remove behavior for ``dhcp-options`` + in path ``ip dhcp-client`` (https://github.com/ansible-collections/community.routeros/issues/148, + https://github.com/ansible-collections/community.routeros/pull/154). + - api_modify - fix handling of disabled keys on creation (https://github.com/ansible-collections/community.routeros/pull/154). + - various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.routeros/pull/149). minor_changes: - - api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). - - api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). - - api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). - - api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/158). - - api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). - - command - workaround for extra characters in stdout in RouterOS versions between - 6.49 and 7.1.5 (https://github.com/ansible-collections/community.routeros/issues/62, - https://github.com/ansible-collections/community.routeros/pull/161). + - api_modify - adapt data for API paths ``ip dhcp-server network`` (https://github.com/ansible-collections/community.routeros/pull/156). + - api_modify - add support for API path ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/159). + - api_modify - add support for ``trap-interfaces`` in API path ``snmp`` (https://github.com/ansible-collections/community.routeros/pull/159). + - api_modify - add support to disable IPv6 in API paths ``ipv6 settings`` + (https://github.com/ansible-collections/community.routeros/pull/158). + - api_modify - support API paths ``ip firewall layer7-protocol`` (https://github.com/ansible-collections/community.routeros/pull/153). + - command - workaround for extra characters in stdout in RouterOS versions + between 6.49 and 7.1.5 (https://github.com/ansible-collections/community.routeros/issues/62, + https://github.com/ansible-collections/community.routeros/pull/161). release_summary: Bugfix and feature release. fragments: - - 153-ip_firewall_layer7-protocol.yml - - 154-ip-dhcp-client-dhcp-options.yml - - 156-ip_dhcp-server_network.yml - - 158-ipv6_settings-disable.yml - - 159-snmp_community.yml - - 161-workaround-prompt-with-space.yml - - 2.8.0.yml - - remove-unneeded-imports.yml + - 153-ip_firewall_layer7-protocol.yml + - 154-ip-dhcp-client-dhcp-options.yml + - 156-ip_dhcp-server_network.yml + - 158-ipv6_settings-disable.yml + - 159-snmp_community.yml + - 161-workaround-prompt-with-space.yml + - 2.8.0.yml + - remove-unneeded-imports.yml release_date: '2023-03-23' 2.8.1: changes: bugfixes: - - facts - do not crash in CLI output preprocessing in unexpected situations - during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, - https://github.com/ansible-collections/community.routeros/pull/177). + - facts - do not crash in CLI output preprocessing in unexpected situations + during line unwrapping (https://github.com/ansible-collections/community.routeros/issues/170, + https://github.com/ansible-collections/community.routeros/pull/177). release_summary: Bugfix release. fragments: - - 177-facts-parsing.yml - - 2.8.1.yml + - 177-facts-parsing.yml + - 2.8.1.yml release_date: '2023-06-14' 2.8.2: changes: bugfixes: - - api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` - path (https://github.com/ansible-collections/community.routeros/issues/179, - https://github.com/ansible-collections/community.routeros/pull/180). + - api_modify, api_info - add missing parameter ``tls`` for the ``tool e-mail`` + path (https://github.com/ansible-collections/community.routeros/issues/179, + https://github.com/ansible-collections/community.routeros/pull/180). release_summary: Bugfix release. fragments: - - 180-fix-tls-in-tool-email.yml - - 2.8.2.yml + - 180-fix-tls-in-tool-email.yml + - 2.8.2.yml release_date: '2023-06-19' 2.8.3: changes: known_issues: - - Ansible markup will show up in raw form on ansible-doc text output for ansible-core - before 2.15. If you have trouble deciphering the documentation markup, please - upgrade to ansible-core 2.15 (or newer), or read the HTML documentation on - https://docs.ansible.com/ansible/devel/collections/community/routeros/. + - Ansible markup will show up in raw form on ansible-doc text output for ansible-core + before 2.15. If you have trouble deciphering the documentation markup, please + upgrade to ansible-core 2.15 (or newer), or read the HTML documentation + on https://docs.ansible.com/ansible/devel/collections/community/routeros/. release_summary: 'Maintenance release with updated documentation. @@ -685,25 +482,235 @@ releases: ' fragments: - - 2.8.3.yml - - semantic-markup.yml + - 2.8.3.yml + - semantic-markup.yml release_date: '2023-06-27' 2.9.0: changes: bugfixes: - - api_modify, api_info - add missing parameter ``engine-id-suffix`` for the - ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, - https://github.com/ansible-collections/community.routeros/pull/190). + - api_modify, api_info - add missing parameter ``engine-id-suffix`` for the + ``snmp`` path (https://github.com/ansible-collections/community.routeros/issues/189, + https://github.com/ansible-collections/community.routeros/pull/190). minor_changes: - - api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man - manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, - https://github.com/ansible-collections/community.routeros/pull/194). - - api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, - https://github.com/ansible-collections/community.routeros/pull/192). + - api_info, api_modify - add path ``caps-man channel`` and enable path ``caps-man + manager interface`` (https://github.com/ansible-collections/community.routeros/issues/193, + https://github.com/ansible-collections/community.routeros/pull/194). + - api_info, api_modify - add path ``ip traffic-flow target`` (https://github.com/ansible-collections/community.routeros/issues/191, + https://github.com/ansible-collections/community.routeros/pull/192). release_summary: Bugfix and feature release. fragments: - - 180-fix-engine-id-suffix-in-snmp.yml - - 192-add-ip_traffic-flow_target-path.yml - - 194-add-caps-man_channel-and-caps-man_manager_interface.yml - - 2.9.0.yml + - 180-fix-engine-id-suffix-in-snmp.yml + - 192-add-ip_traffic-flow_target-path.yml + - 194-add-caps-man_channel-and-caps-man_manager_interface.yml + - 2.9.0.yml release_date: '2023-08-15' + 2.10.0: + changes: + bugfixes: + - api_info, api_modify - in the ``snmp`` path, ensure that ``engine-id-suffix`` + is only available on RouterOS 7.10+, and that ``engine-id`` is read-only + on RouterOS 7.10+ (https://github.com/ansible-collections/community.routeros/issues/208, + https://github.com/ansible-collections/community.routeros/pull/218). + minor_changes: + - api_info - add new ``include_read_only`` option to select behavior for read-only + values. By default these are not returned (https://github.com/ansible-collections/community.routeros/pull/213). + - api_info, api_modify - add support for ``address-list`` and ``match-subdomain`` + introduced by RouterOS 7.7 in the ``ip dns static`` path (https://github.com/ansible-collections/community.routeros/pull/197). + - api_info, api_modify - add support for ``user``, ``time`` and ``gmt-offset`` + under the ``system clock`` path (https://github.com/ansible-collections/community.routeros/pull/210). + - api_info, api_modify - add support for the ``interface ppp-client`` path + (https://github.com/ansible-collections/community.routeros/pull/199). + - api_info, api_modify - add support for the ``interface wireless`` path (https://github.com/ansible-collections/community.routeros/pull/195). + - api_info, api_modify - add support for the ``iot modbus`` path (https://github.com/ansible-collections/community.routeros/pull/205). + - api_info, api_modify - add support for the ``ip dhcp-server option`` and + ``ip dhcp-server option sets`` paths (https://github.com/ansible-collections/community.routeros/pull/223). + - api_info, api_modify - add support for the ``ip upnp interfaces``, ``tool + graphing interface``, ``tool graphing resource`` paths (https://github.com/ansible-collections/community.routeros/pull/227). + - api_info, api_modify - add support for the ``ipv6 firewall nat`` path (https://github.com/ansible-collections/community.routeros/pull/204). + - api_info, api_modify - add support for the ``mode`` property in ``ip neighbor + discovery-settings`` introduced in RouterOS 7.7 (https://github.com/ansible-collections/community.routeros/pull/198). + - api_info, api_modify - add support for the ``port remote-access`` path (https://github.com/ansible-collections/community.routeros/pull/224). + - api_info, api_modify - add support for the ``routing filter rule`` and ``routing + filter select-rule`` paths (https://github.com/ansible-collections/community.routeros/pull/200). + - api_info, api_modify - add support for the ``routing table`` path in RouterOS + 7 (https://github.com/ansible-collections/community.routeros/pull/215). + - api_info, api_modify - add support for the ``tool netwatch`` path in RouterOS + 7 (https://github.com/ansible-collections/community.routeros/pull/216). + - api_info, api_modify - add support for the ``user settings`` path (https://github.com/ansible-collections/community.routeros/pull/201). + - api_info, api_modify - add support for the ``user`` path (https://github.com/ansible-collections/community.routeros/pull/211). + - api_info, api_modify - finalize fields for the ``interface wireless security-profiles`` + path and enable it (https://github.com/ansible-collections/community.routeros/pull/203). + - api_info, api_modify - finalize fields for the ``ppp profile`` path and + enable it (https://github.com/ansible-collections/community.routeros/pull/217). + - api_modify - add new ``handle_read_only`` and ``handle_write_only`` options + to handle the module's behavior for read-only and write-only fields (https://github.com/ansible-collections/community.routeros/pull/213). + - api_modify, api_info - support API paths ``routing id``, ``routing bgp connection`` + (https://github.com/ansible-collections/community.routeros/pull/220). + release_summary: Bugfix and feature release. + fragments: + - 195-add-interface-wireless-data.yml + - 197-dns-static-addrlist-matchsubdomain.yml + - 198-ip-nd-mode.yml + - 199-add-interface-pppclient.yml + - 2.10.0.yml + - 200-add-routing-filter.yml + - 201-add-user-settings.yml + - 203-wireless-security-profiles.yml + - 204-add-ipv6-firewall-nat.yml + - 205-add-iot-modbus.yml + - 210-date-time-gmt-offset.yml + - 211-user.yml + - 213-read-write-only.yml + - 215-add-routing-table.yml + - 216-add-tool-netwatch.yml + - 217-ppp-profiles.yml + - 218-snmp-engine-id.yml + - 220-routing-id-bgp-connection.yml + - 223-add-ip-dhcp-server-option.yml + - 224-add-port-remote-access.yml + - 227-add-upnp-graphing.yml + release_date: '2023-10-08' + 2.11.0: + changes: + minor_changes: + - api_info, api_modify - add missing DoH parameters ``doh-max-concurrent-queries``, + ``doh-max-server-connections``, and ``doh-timeout`` to the ``ip dns`` path + (https://github.com/ansible-collections/community.routeros/issues/230, https://github.com/ansible-collections/community.routeros/pull/235) + - api_info, api_modify - add missing parameters ``address-list``, ``address-list-timeout``, + ``randomise-ports``, and ``realm`` to subpaths of the ``ip firewall`` path + (https://github.com/ansible-collections/community.routeros/issues/236, https://github.com/ansible-collections/community.routeros/pull/237). + - api_info, api_modify - mark the ``interface wireless`` parameter ``running`` + as read-only (https://github.com/ansible-collections/community.routeros/pull/233). + - api_info, api_modify - set the default value to ``false`` for the ``disabled`` + parameter in some more paths where it can be seen in the documentation (https://github.com/ansible-collections/community.routeros/pull/237). + - api_modify - add missing ``comment`` attribute to ``/routing id`` (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add missing attributes to the ``routing bgp connection`` path + (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - add versioning to the ``/tool e-mail`` path (RouterOS 7.12 + release) (https://github.com/ansible-collections/community.routeros/pull/234). + - api_modify - make ``/ip traffic-flow target`` a multiple value attribute + (https://github.com/ansible-collections/community.routeros/pull/234). + release_summary: Feature and bugfix release. + fragments: + - 2.11.0.yml + - 233-wireless-running-read-only.yml + - 234-bugfixes-and-update-adaptations.yml + - 235-add-missing-dns-attributes.yml + - 237-add-missing-ip-firewall-attributes.yml + release_date: '2023-12-03' + 2.12.0: + changes: + minor_changes: + - api_info, api_modify - add ``interface ovpn-client`` path (https://github.com/ansible-collections/community.routeros/issues/242, + https://github.com/ansible-collections/community.routeros/pull/244). + - api_info, api_modify - add ``radius`` path (https://github.com/ansible-collections/community.routeros/issues/241, + https://github.com/ansible-collections/community.routeros/pull/245). + - api_info, api_modify - add ``routing rule`` path (https://github.com/ansible-collections/community.routeros/issues/162, + https://github.com/ansible-collections/community.routeros/pull/246). + - api_info, api_modify - add missing path ``routing bgp template`` (https://github.com/ansible-collections/community.routeros/pull/243). + - api_info, api_modify - add support for the ``tx-power`` attribute in ``interface + wireless`` (https://github.com/ansible-collections/community.routeros/pull/239). + - api_info, api_modify - removed ``host`` primary key in ``tool netwatch`` + path (https://github.com/ansible-collections/community.routeros/pull/248). + - api_modify, api_info - added support for ``interface wifiwave2`` (https://github.com/ansible-collections/community.routeros/pull/226). + release_summary: Feature release. + fragments: + - 2.12.0.yml + - 226-support-for-WifiWave2.yml + - 239-wireless-tx-power.yml + - 243-add-routing-bgp-template-path.yml + - 244-add-interface-ovpn-client-path.yml + - 245-add-radius-path.yml + - 246-add-routing-rule-path.yml + - 247-removed-primary-key-host-in-tool-netwatch.yml + release_date: '2024-01-21' + 2.13.0: + changes: + bugfixes: + - facts - fix date not getting removed for idempotent config export (https://github.com/ansible-collections/community.routeros/pull/262). + minor_changes: + - api_info, api_modify - make path ``user group`` modifiable and add ``comment`` + attribute (https://github.com/ansible-collections/community.routeros/issues/256, + https://github.com/ansible-collections/community.routeros/pull/257). + - api_modify, api_info - add support for the ``ip vrf`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/259) + release_summary: Bugfix and feature release. + fragments: + - 2.13.0.yml + - 257-make-user_group-modifiable.yml + - 259-add-routeros7-support-for-ip-vrf.yml + - 262-fix-date-removal.yml + release_date: '2024-02-25' + 2.14.0: + changes: + minor_changes: + - api_info, api_modify - add read-only fields ``installed-version``, ``latest-version`` + and ``status`` in ``system package update`` (https://github.com/ansible-collections/community.routeros/pull/263). + - api_info, api_modify - added support for ``interface wifi`` and its sub-paths + (https://github.com/ansible-collections/community.routeros/pull/266). + - api_info, api_modify - remove default value for read-only ``running`` field + in ``interface wireless`` (https://github.com/ansible-collections/community.routeros/pull/264). + release_summary: Feature release. + fragments: + - 2.14.0.yml + - 263-sys-pkg-update.yml + - 264-wireless-running-default.yml + - 266-interface-wifi.yml + release_date: '2024-03-25' + 2.15.0: + changes: + minor_changes: + - api_info, api_modify - Add RouterOS 7.x support to ``/mpls ldp`` path (https://github.com/ansible-collections/community.routeros/pull/271). + - api_info, api_modify - add ``/ip route rule`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/278). + - api_info, api_modify - add ``/routing filter`` path for RouterOS 6.x (https://github.com/ansible-collections/community.routeros/pull/279). + - api_info, api_modify - add default value for ``from-pool`` field in ``/ipv6 + address`` (https://github.com/ansible-collections/community.routeros/pull/270). + - api_info, api_modify - add missing path ``/interface pppoe-server server`` + (https://github.com/ansible-collections/community.routeros/pull/273). + - api_info, api_modify - add missing path ``/ip dhcp-relay`` (https://github.com/ansible-collections/community.routeros/pull/276). + - api_info, api_modify - add missing path ``/queue simple`` (https://github.com/ansible-collections/community.routeros/pull/269). + - api_info, api_modify - add missing path ``/queue type`` (https://github.com/ansible-collections/community.routeros/pull/274). + - api_info, api_modify - add missing paths ``/routing bgp aggregate``, ``/routing + bgp network`` and ``/routing bgp peer`` (https://github.com/ansible-collections/community.routeros/pull/277). + - api_info, api_modify - add support for paths ``/mpls interface``, ``/mpls + ldp accept-filter``, ``/mpls ldp advertise-filter`` and ``mpls ldp interface`` + (https://github.com/ansible-collections/community.routeros/pull/272). + release_summary: Feature release. + fragments: + - 2.15.0.yml + - 269-add-queue_simple-path.yml + - 270_fix_ipv6_from_pool_default_value.yml + - 271-mpls_ldp_routeros_7_support.yml + - 272-additional_mpls_path_support.yml + - 273-add_interface_pppoe-server_support.yml + - 274-add_queue_type_path.yml + - 276-add_ip_dhcp-relay_path.yml + - 277-add_routing_bgp_paths.yml + - 278-add_ip_route_rule_path.yml + - 279-add_routing_filter_path.yml + release_date: '2024-04-20' + 2.16.0: + changes: + minor_changes: + - api_info, api_modify - add missing path ``/ppp secret`` (https://github.com/ansible-collections/community.routeros/pull/286). + - api_info, api_modify - minor changes ``/interface ethernet`` path fields + (https://github.com/ansible-collections/community.routeros/pull/288). + release_summary: Feature release. + fragments: + - 2.16.0.yml + - 286-add_ppp_secret_path.yml + - 288-interface_ethernet_values.yml + release_date: '2024-06-16' + 2.17.0: + changes: + minor_changes: + - api_info, api_modify - add ``system health settings`` path (https://github.com/ansible-collections/community.routeros/pull/294). + - api_info, api_modify - add missing path ``/system resource irq rps`` (https://github.com/ansible-collections/community.routeros/pull/295). + - api_info, api_modify - add parameter ``host-key-type`` for ``ip ssh`` path + (https://github.com/ansible-collections/community.routeros/issues/280, https://github.com/ansible-collections/community.routeros/pull/297). + release_summary: Feature release. + fragments: + - 2.17.0.yml + - 294-add-system-health-settings-path.yml + - 295-add_system_resource_irq_rps_path.yml + - 297-add-ip-ssh-host-key-type.yml + release_date: '2024-07-09' diff --git a/changelogs/config.yaml b/changelogs/config.yaml index bb3c08b..a02e530 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -13,28 +13,30 @@ flatmap: true new_plugins_after_name: removed_features notesdir: fragments output_formats: -- rst -- md + - rst + - md prelude_section_name: release_summary prelude_section_title: Release Summary sections: -- - major_changes - - Major Changes -- - minor_changes - - Minor Changes -- - breaking_changes - - Breaking Changes / Porting Guide -- - deprecated_features - - Deprecated Features -- - removed_features - - Removed Features (previously deprecated) -- - security_fixes - - Security Fixes -- - bugfixes - - Bugfixes -- - known_issues - - Known Issues + - - major_changes + - Major Changes + - - minor_changes + - Minor Changes + - - breaking_changes + - Breaking Changes / Porting Guide + - - deprecated_features + - Deprecated Features + - - removed_features + - Removed Features (previously deprecated) + - - security_fixes + - Security Fixes + - - bugfixes + - Bugfixes + - - known_issues + - Known Issues title: Community RouterOS trivial_section_name: trivial use_fqcn: true add_plugin_period: true +changelog_nice_yaml: true +changelog_sort: version From 5ee2af49b84af7fe8f059aa0d1950a98e2e8c84e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 12 Jul 2024 19:11:49 +0200 Subject: [PATCH 252/365] Small README change to hopefully trigger code coverage upload. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f34a749..757ddb0 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ See [Ansible's dev guide](https://docs.ansible.com/ansible/devel/dev_guide/devel ## Release notes -See the [changelog](https://github.com/ansible-collections/community.routeros/blob/main/CHANGELOG.md). +See the [collection's changelog](https://github.com/ansible-collections/community.routeros/blob/main/CHANGELOG.md). ## Roadmap From 8c62d4619835380aa89797a74c01d30942171336 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 21 Jul 2024 23:18:31 +0200 Subject: [PATCH 253/365] Add IPv4 DHCP option matcher, minor fixes (#300) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix typos in comment on IPsec policy "template" field * Move IPv4 DHCP server API data next to other DHCP APIs * Set default for "force" field on DHCP options Without the default value removing it from the options after it's been set once leads to an error: > Key "force" cannot be removed for name="…" * Add IPv4 DHCP option matcher RouterOS 7.4 and newer implement matchers for the Vendor ID provided by DHCP clients. RouterOS 7.16 will add a new `matching-type` property, but it's not in a stable release yet. Upstream documentation: https://help.mikrotik.com/docs/display/ROS/DHCP#DHCP-Genericmatcher --- .../300-add-ip-dhcp-server-matcher.yml | 2 + .../300-set-ip-dhcp-option-force-default.yml | 2 + plugins/module_utils/_api_data.py | 84 +++++++++++-------- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 5 files changed, 57 insertions(+), 33 deletions(-) create mode 100644 changelogs/fragments/300-add-ip-dhcp-server-matcher.yml create mode 100644 changelogs/fragments/300-set-ip-dhcp-option-force-default.yml diff --git a/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml b/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml new file mode 100644 index 0000000..cf97e06 --- /dev/null +++ b/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ip dhcp-server matcher`` path (https://github.com/ansible-collections/community.routeros/issues/300). diff --git a/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml b/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml new file mode 100644 index 0000000..5158fc3 --- /dev/null +++ b/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/issues/300). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 061846f..218b379 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -774,36 +774,6 @@ PATHS = { )), ], ), - ('ip', 'dhcp-server'): APIData( - unversioned=VersionedAPIData( - fully_understood=True, - primary_keys=('name', ), - fields={ - 'address-pool': KeyInfo(default='static-only'), - 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), - 'always-broadcast': KeyInfo(can_disable=True, remove_value=False), - 'authoritative': KeyInfo(default=True), - 'bootp-lease-time': KeyInfo(default='forever'), - 'bootp-support': KeyInfo(can_disable=True, remove_value='static'), - 'client-mac-limit': KeyInfo(can_disable=True, remove_value='unlimited'), - 'comment': KeyInfo(can_disable=True, remove_value=''), - 'conflict-detection': KeyInfo(can_disable=True, remove_value=True), - 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), - 'dhcp-option-set': KeyInfo(can_disable=True, remove_value='none'), - 'disabled': KeyInfo(default=False), - 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), - 'interface': KeyInfo(required=True), - 'lease-script': KeyInfo(default=''), - 'lease-time': KeyInfo(default='10m'), - 'name': KeyInfo(), - 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), - 'relay': KeyInfo(can_disable=True, remove_value='0.0.0.0'), - 'server-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), - 'use-framed-as-classless': KeyInfo(can_disable=True, remove_value=True), - 'use-radius': KeyInfo(default=False), - }, - ), - ), ('routing', 'filter'): APIData( versioned=[ ('7', '<', VersionedAPIData( @@ -2679,6 +2649,36 @@ PATHS = { }, ), ), + ('ip', 'dhcp-server'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(default='static-only'), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'always-broadcast': KeyInfo(can_disable=True, remove_value=False), + 'authoritative': KeyInfo(default=True), + 'bootp-lease-time': KeyInfo(default='forever'), + 'bootp-support': KeyInfo(can_disable=True, remove_value='static'), + 'client-mac-limit': KeyInfo(can_disable=True, remove_value='unlimited'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'conflict-detection': KeyInfo(can_disable=True, remove_value=True), + 'delay-threshold': KeyInfo(can_disable=True, remove_value='none'), + 'dhcp-option-set': KeyInfo(can_disable=True, remove_value='none'), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), + 'interface': KeyInfo(required=True), + 'lease-script': KeyInfo(default=''), + 'lease-time': KeyInfo(default='10m'), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'relay': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'server-address': KeyInfo(can_disable=True, remove_value='0.0.0.0'), + 'use-framed-as-classless': KeyInfo(can_disable=True, remove_value=True), + 'use-radius': KeyInfo(default=False), + }, + ), + ), ('ip', 'dhcp-server', 'config'): APIData( unversioned=VersionedAPIData( single_value=True, @@ -2738,7 +2738,7 @@ PATHS = { 'code': KeyInfo(required=True), 'name': KeyInfo(), 'value': KeyInfo(default=''), - 'force': KeyInfo(), + 'force': KeyInfo(default=False), }, ), ), @@ -2752,6 +2752,23 @@ PATHS = { }, ), ), + ('ip', 'dhcp-server', 'matcher'): APIData( + versioned=[ + ('7.4', '>=', VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(default='none'), + 'code': KeyInfo(required=True), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(required=True), + 'option-set': KeyInfo(), + 'server': KeyInfo(default='all'), + 'value': KeyInfo(required=True), + }, + )), + ], + ), ('ip', 'dns'): APIData( unversioned=VersionedAPIData( single_value=True, @@ -4966,9 +4983,10 @@ PATHS = { 'protocol': KeyInfo(default='all'), 'src-address': KeyInfo(), 'src-port': KeyInfo(default='any'), + # The template field can't really be changed once the item is + # created. This config captures the behavior best as it can + # i.e. template=yes is shown, template=no is hidden. 'template': KeyInfo(can_disable=True, remove_value=False), - # the tepmlate field can't really be changed once the item is created. This config captures the behavior best as it can - # i.e. tepmplate=yes is shown, tepmlate=no is hidden 'tunnel': KeyInfo(default=False), }, ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index e8d8663..7f45ef5 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -125,6 +125,7 @@ options: - ip dhcp-server - ip dhcp-server config - ip dhcp-server lease + - ip dhcp-server matcher - ip dhcp-server network - ip dhcp-server option - ip dhcp-server option sets diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 5cb1cd8..eb06566 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -134,6 +134,7 @@ options: - ip dhcp-server - ip dhcp-server config - ip dhcp-server lease + - ip dhcp-server matcher - ip dhcp-server network - ip dhcp-server option - ip dhcp-server option sets From ba806c05936c316f760da54eab54e689b8022702 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 1 Aug 2024 16:40:16 +0200 Subject: [PATCH 254/365] Add support for the "routing ospf static-neighbor" path (#302) Upstream documentation: https://help.mikrotik.com/docs/display/ROS/OSPF#OSPF-StaticNeighbourconfiguration Signed-off-by: Michael Hanselmann --- .../fragments/300-add-ip-dhcp-server-matcher.yml | 2 +- .../300-set-ip-dhcp-option-force-default.yml | 2 +- changelogs/fragments/302-ospf-static-neighbor.yml | 2 ++ plugins/module_utils/_api_data.py | 15 +++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 6 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/302-ospf-static-neighbor.yml diff --git a/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml b/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml index cf97e06..c80a3a3 100644 --- a/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml +++ b/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml @@ -1,2 +1,2 @@ minor_changes: - - api_info, api_modify - add support for the ``ip dhcp-server matcher`` path (https://github.com/ansible-collections/community.routeros/issues/300). + - api_info, api_modify - add support for the ``ip dhcp-server matcher`` path (https://github.com/ansible-collections/community.routeros/pull/300). diff --git a/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml b/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml index 5158fc3..1f9585d 100644 --- a/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml +++ b/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml @@ -1,2 +1,2 @@ minor_changes: - - api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/issues/300). + - api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/pull/300). diff --git a/changelogs/fragments/302-ospf-static-neighbor.yml b/changelogs/fragments/302-ospf-static-neighbor.yml new file mode 100644 index 0000000..5f93ec4 --- /dev/null +++ b/changelogs/fragments/302-ospf-static-neighbor.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing ospf static-neighbor`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/302). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 218b379..685c120 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -956,6 +956,21 @@ PATHS = { }, ), ), + ('routing', 'ospf', 'static-neighbor'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'address': KeyInfo(required=True), + 'area': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'instance-id': KeyInfo(default=0), + 'poll-interval': KeyInfo(default='2m'), + }, + )), + ], + ), ('routing', 'ospf-v3', 'instance'): APIData( unversioned=VersionedAPIData( unknown_mechanism=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 7f45ef5..5f47c35 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -209,6 +209,7 @@ options: - routing ospf area range - routing ospf instance - routing ospf interface-template + - routing ospf static-neighbor - routing pimsm instance - routing pimsm interface-template - routing rip diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index eb06566..195b2a9 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -218,6 +218,7 @@ options: - routing ospf area range - routing ospf instance - routing ospf interface-template + - routing ospf static-neighbor - routing pimsm instance - routing pimsm interface-template - routing rip From 64ee613a0d7ac1f49f9d9775d825232fa84fada1 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 1 Aug 2024 17:06:02 +0200 Subject: [PATCH 255/365] Add support for the "ipv6 nd prefix" path (#303) Upstream documentation: https://help.mikrotik.com/docs/display/ROS/IPv6+Neighbor+Discovery#IPv6NeighborDiscovery-Prefix --- changelogs/fragments/303-add-ipv6-nd-prefix.yml | 2 ++ plugins/module_utils/_api_data.py | 16 ++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/303-add-ipv6-nd-prefix.yml diff --git a/changelogs/fragments/303-add-ipv6-nd-prefix.yml b/changelogs/fragments/303-add-ipv6-nd-prefix.yml new file mode 100644 index 0000000..b28915a --- /dev/null +++ b/changelogs/fragments/303-add-ipv6-nd-prefix.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ipv6 nd prefix`` path (https://github.com/ansible-collections/community.routeros/pull/303). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 685c120..3401d64 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3697,6 +3697,22 @@ PATHS = { }, ), ), + ('ipv6', 'nd', 'prefix'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + '6to4-interface': KeyInfo(default='none'), + 'autonomous': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'on-link': KeyInfo(default=True), + 'preferred-lifetime': KeyInfo(), + 'prefix': KeyInfo(), + 'valid-lifetime': KeyInfo(), + }, + ), + ), ('ipv6', 'nd', 'prefix', 'default'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5f47c35..4a5eff4 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -174,6 +174,7 @@ options: - ipv6 firewall nat - ipv6 firewall raw - ipv6 nd + - ipv6 nd prefix - ipv6 nd prefix default - ipv6 route - ipv6 settings diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 195b2a9..42abafb 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -183,6 +183,7 @@ options: - ipv6 firewall nat - ipv6 firewall raw - ipv6 nd + - ipv6 nd prefix - ipv6 nd prefix default - ipv6 route - ipv6 settings From 6986e2fc25861db213f96fc499ab59c1ed401c43 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 5 Aug 2024 20:46:28 +0200 Subject: [PATCH 256/365] Support name and is-responder properties on Wireguard peers (#304) From the RouterOS 7.15 changelog: ``` *) wireguard - added option to mark peer as responder only; *) wireguard - added peer "name" field and display it in logs; ``` --- changelogs/fragments/304-wireguard-name-responder.yml | 2 ++ plugins/module_utils/_api_data.py | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 changelogs/fragments/304-wireguard-name-responder.yml diff --git a/changelogs/fragments/304-wireguard-name-responder.yml b/changelogs/fragments/304-wireguard-name-responder.yml new file mode 100644 index 0000000..e333082 --- /dev/null +++ b/changelogs/fragments/304-wireguard-name-responder.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``name`` and ``is-responder`` properties under the ``interface wireguard peers`` path introduced in RouterOS 7.15 (https://github.com/ansible-collections/community.routeros/pull/304). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 3401d64..9cdb810 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2340,6 +2340,10 @@ PATHS = { 'preshared-key': KeyInfo(can_disable=True, remove_value=''), 'public-key': KeyInfo(), }, + versioned_fields=[ + ([('7.15', '>=')], 'name', KeyInfo()), + ([('7.15', '>=')], 'is-responder', KeyInfo()), + ], ), ), ('interface', 'wireless'): APIData( From 78466d0de4abf3760ed0421defa578349dee65e2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Aug 2024 20:12:54 +0200 Subject: [PATCH 257/365] Prepare 2.18.0 release. --- changelogs/fragments/2.18.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.18.0.yml diff --git a/changelogs/fragments/2.18.0.yml b/changelogs/fragments/2.18.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/2.18.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index 1a455fd..cbec7c0 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.17.0 +version: 2.18.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 877c9fa4fe5138f2e001c3ea320f1bf88a3654e4 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 11 Aug 2024 22:29:36 +0200 Subject: [PATCH 258/365] Fix default of ingress-filtering for ROS < 7. (#306) --- changelogs/fragments/306-ingress-filtering-ros6.yml | 2 ++ plugins/module_utils/_api_data.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/306-ingress-filtering-ros6.yml diff --git a/changelogs/fragments/306-ingress-filtering-ros6.yml b/changelogs/fragments/306-ingress-filtering-ros6.yml new file mode 100644 index 0000000..fc9ea73 --- /dev/null +++ b/changelogs/fragments/306-ingress-filtering-ros6.yml @@ -0,0 +1,2 @@ +bugfixes: + - "api_modify, api_info - change the default of ``ingress-filtering`` in paths ``interface bridge`` and ``interface bridge port`` back to ``false`` for RouterOS before version 7 (https://github.com/ansible-collections/community.routeros/pull/305)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 9cdb810..478cd2e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -259,6 +259,10 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, primary_keys=('name', ), + versioned_fields=[ + ([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)), + ([('7.0', '>=')], 'ingress-filtering', KeyInfo(default=True)), + ], fields={ 'admin-mac': KeyInfo(default=''), 'ageing-time': KeyInfo(default='5m'), @@ -273,7 +277,6 @@ PATHS = { 'frame-types': KeyInfo(default='admit-all'), 'forward-delay': KeyInfo(default='15s'), 'igmp-snooping': KeyInfo(default=False), - 'ingress-filtering': KeyInfo(default=True), 'max-message-age': KeyInfo(default='20s'), 'mtu': KeyInfo(default='auto'), 'name': KeyInfo(), @@ -1310,6 +1313,10 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, primary_keys=('interface', ), + versioned_fields=[ + ([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)), + ([('7.0', '>=')], 'ingress-filtering', KeyInfo(default=True)), + ], fields={ 'auto-isolate': KeyInfo(default=False), 'bpdu-guard': KeyInfo(default=False), @@ -1322,7 +1329,6 @@ PATHS = { 'frame-types': KeyInfo(default='admit-all'), 'horizon': KeyInfo(default='none'), 'hw': KeyInfo(default=True), - 'ingress-filtering': KeyInfo(default=True), 'interface': KeyInfo(), 'internal-path-cost': KeyInfo(default=10), 'learn': KeyInfo(default='auto'), From 1859ef9d35c3a8749f1a7469246db15c36e11dce Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 12 Aug 2024 17:05:12 +0200 Subject: [PATCH 259/365] Improve communication info. (#307) --- README.md | 18 ++++++++++++++++++ docs/docsite/links.yml | 7 ++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 757ddb0..1ef42b5 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,24 @@ Provides modules for [Ansible](https://www.ansible.com/community) to manage [Mik You can find [documentation for the modules and plugins in this collection here](https://docs.ansible.com/ansible/devel/collections/community/routeros/). +## Code of Conduct + +We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our interactions within this project. + +If you encounter abusive behavior violating the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html), please refer to the [policy violations](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html#policy-violations) section of the Code of Conduct for information on how to raise a complaint. + +## Communication + +* Join the Ansible forum: + * [Get Help](https://forum.ansible.com/c/help/6): get help or help others. This is for questions about modules or plugins in the collection. + * [Posts tagged with 'routeros'](https://forum.ansible.com/tag/routeros): subscribe to participate in RouterOS related conversations. + * [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts. + * [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events. + +* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes. + +For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html). + ## Tested with Ansible Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, and ansible-core 2.17 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. diff --git a/docs/docsite/links.yml b/docs/docsite/links.yml index ef9c985..9324e87 100644 --- a/docs/docsite/links.yml +++ b/docs/docsite/links.yml @@ -9,6 +9,8 @@ edit_on_github: path_prefix: '' extra_links: + - description: Ask for help (RouterOS) + url: https://forum.ansible.com/tags/c/help/6/none/routeros - description: Submit a bug report url: https://github.com/ansible-collections/community.routeros/issues/new?assignees=&labels=&template=bug_report.md - description: Request a feature @@ -26,6 +28,9 @@ communication: - topic: Ansible Project List url: https://groups.google.com/g/ansible-project forums: - - topic: Ansible Forum + - topic: "Ansible Forum: General usage and support questions" # The following URL directly points to the "Get Help" section url: https://forum.ansible.com/c/help/6/none + - topic: "Ansible Forum: Discussions about RouterOS" + # The following URL directly points to the "routeros" tag + url: https://forum.ansible.com/tag/routeros From 49cd8a2b2f28217f81bd3537c2922b8c6e26523b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 12 Aug 2024 21:15:15 +0200 Subject: [PATCH 260/365] Announce dropping support for ansible-core < 2.15 in next major release. (#308) --- changelogs/fragments/deprecate-eol-ansible-core.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/fragments/deprecate-eol-ansible-core.yml diff --git a/changelogs/fragments/deprecate-eol-ansible-core.yml b/changelogs/fragments/deprecate-eol-ansible-core.yml new file mode 100644 index 0000000..630f7c9 --- /dev/null +++ b/changelogs/fragments/deprecate-eol-ansible-core.yml @@ -0,0 +1,5 @@ +deprecated_features: + - "The collection deprecates support for all Ansible/ansible-base/ansible-core versions that are currently End of Life, + `according to the ansible-core support matrix `__. + This means that the next major release of the collection will no longer support Ansible 2.9, ansible-base 2.10, ansible-core 2.11, + ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14." From 0a9b749508c1dff6636fe3512ebc2c67578f148c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 12 Aug 2024 21:16:59 +0200 Subject: [PATCH 261/365] api_modify/api_info: add `restrict` option (#305) * Allow to restrict api_info output. * Allow to restrict what api_modify modifies. * Add changelog. * Fix docs. * Move shared code/docs to module utils and doc fragments. * Refactor and allow to match by regex. * Simplify rules, allow to invert rule matcher. * Add more tests. --- changelogs/fragments/305-api-restrict.yml | 3 + plugins/doc_fragments/api.py | 41 ++ plugins/module_utils/_api_helper.py | 102 +++++ plugins/modules/api_info.py | 27 ++ plugins/modules/api_modify.py | 65 ++- .../plugins/module_utils/test__api_helper.py | 377 ++++++++++++++++++ tests/unit/plugins/modules/test_api_info.py | 166 ++++++++ 7 files changed, 776 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/305-api-restrict.yml create mode 100644 plugins/module_utils/_api_helper.py create mode 100644 tests/unit/plugins/module_utils/test__api_helper.py diff --git a/changelogs/fragments/305-api-restrict.yml b/changelogs/fragments/305-api-restrict.yml new file mode 100644 index 0000000..3b737ea --- /dev/null +++ b/changelogs/fragments/305-api-restrict.yml @@ -0,0 +1,3 @@ +minor_changes: + - "api_info - allow to restrict the output by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305)." + - "api_modify - allow to restrict what is updated by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305)." diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index 7f77e8f..b0ad979 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -95,3 +95,44 @@ seealso: - ref: ansible_collections.community.routeros.docsite.api-guide description: How to connect to RouterOS devices with the RouterOS API ''' + + RESTRICT = r''' +options: + restrict: + type: list + elements: dict + suboptions: + field: + description: + - The field whose values to restrict. + required: true + type: str + match_disabled: + description: + - Whether disabled or not provided values should match. + type: bool + default: false + values: + description: + - The values of the field to limit to. + - >- + Note that the types of the values are important. If you provide a string V("0"), + and librouteros converts the value returned by the API to the integer V(0), + then this will not match. If you are not sure, better include both variants: + both the string and the integer. + type: list + elements: raw + regex: + description: + - A regular expression matching values of the field to limit to. + - Note that all values will be converted to strings before matching. + - It is not possible to match disabled values with regular expressions. + Set O(restrict[].match_disabled=true) if you also want to match disabled values. + type: str + invert: + description: + - Invert the condition. This affects O(restrict[].match_disabled), O(restrict[].values), + and O(restrict[].regex). + type: bool + default: false +''' diff --git a/plugins/module_utils/_api_helper.py b/plugins/module_utils/_api_helper.py new file mode 100644 index 0000000..ffd897f --- /dev/null +++ b/plugins/module_utils/_api_helper.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +# The data inside here is private to this collection. If you use this from outside the collection, +# you are on your own. There can be random changes to its format even in bugfix releases! + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import re + +from ansible.module_utils.common.text.converters import to_text + + +def validate_and_prepare_restrict(module, path_info): + restrict = module.params['restrict'] + if restrict is None: + return None + restrict_data = [] + for rule in restrict: + field = rule['field'] + if field.startswith('!'): + module.fail_json(msg='restrict: the field name "{0}" must not start with "!"'.format(field)) + f = path_info.fields.get(field) + if f is None: + module.fail_json(msg='restrict: the field "{0}" does not exist for this path'.format(field)) + + new_rule = dict( + field=field, + match_disabled=rule['match_disabled'], + invert=rule['invert'], + ) + if rule['values'] is not None: + new_rule['values'] = rule['values'] + if rule['regex'] is not None: + regex = rule['regex'] + try: + new_rule['regex'] = re.compile(regex) + new_rule['regex_source'] = regex + except Exception as exc: + module.fail_json(msg='restrict: invalid regular expression "{0}": {1}'.format(regex, exc)) + restrict_data.append(new_rule) + return restrict_data + + +def _value_to_str(value): + if value is None: + return None + value_str = to_text(value) + if isinstance(value, bool): + value_str = value_str.lower() + return value_str + + +def _test_rule_except_invert(value, rule): + if value is None and rule['match_disabled']: + return True + if 'values' in rule and value in rule['values']: + return True + if 'regex' in rule and value is not None and rule['regex'].match(_value_to_str(value)): + return True + return False + + +def restrict_entry_accepted(entry, path_info, restrict_data): + if restrict_data is None: + return True + for rule in restrict_data: + # Obtain field and value + field = rule['field'] + field_info = path_info.fields[field] + value = entry.get(field) + if value is None: + value = field_info.default + if field not in entry and field_info.absent_value: + value = field_info.absent_value + + # Check + matches_rule = _test_rule_except_invert(value, rule) + if rule['invert']: + matches_rule = not matches_rule + if not matches_rule: + return False + return True + + +def restrict_argument_spec(): + return dict( + restrict=dict( + type='list', + elements='dict', + options=dict( + field=dict(type='str', required=True), + match_disabled=dict(type='bool', default=False), + values=dict(type='list', elements='raw'), + regex=dict(type='str'), + invert=dict(type='bool', default=False), + ), + ), + ) diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 4a5eff4..24fd8fe 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -26,6 +26,7 @@ description: L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). extends_documentation_fragment: - community.routeros.api + - community.routeros.api.restrict - community.routeros.attributes - community.routeros.attributes.actiongroup_api - community.routeros.attributes.info_module @@ -301,6 +302,10 @@ options: type: bool default: false version_added: 2.10.0 + restrict: + description: + - Restrict output to entries matching the following criteria. + version_added: 2.18.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -318,6 +323,18 @@ EXAMPLES = ''' path: ip address register: ip_addresses +- name: Print data for IP addresses + ansible.builtin.debug: + var: ip_addresses.result + +- name: Get IP addresses + community.routeros.api_info: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: ip address + register: ip_addresses + - name: Print data for IP addresses ansible.builtin.debug: var: ip_addresses.result @@ -358,6 +375,12 @@ from ansible_collections.community.routeros.plugins.module_utils._api_data impor split_path, ) +from ansible_collections.community.routeros.plugins.module_utils._api_helper import ( + restrict_argument_spec, + restrict_entry_accepted, + validate_and_prepare_restrict, +) + try: from librouteros.exceptions import LibRouterosError except Exception: @@ -383,6 +406,7 @@ def main(): include_read_only=dict(type='bool', default=False), ) module_args.update(api_argument_spec()) + module_args.update(restrict_argument_spec()) module = AnsibleModule( argument_spec=module_args, @@ -411,6 +435,7 @@ def main(): include_dynamic = module.params['include_dynamic'] include_builtin = module.params['include_builtin'] include_read_only = module.params['include_read_only'] + restrict_data = validate_and_prepare_restrict(module, path_info) try: api_path = compose_api_path(api, path) @@ -423,6 +448,8 @@ def main(): if not include_builtin: if entry.get('builtin', False): continue + if not restrict_entry_accepted(entry, path_info, restrict_data): + continue if not unfiltered: for k in list(entry): if k == '.id': diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 42abafb..a2a2c10 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -32,6 +32,7 @@ requirements: - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6 extends_documentation_fragment: - community.routeros.api + - community.routeros.api.restrict - community.routeros.attributes - community.routeros.attributes.actiongroup_api attributes: @@ -333,6 +334,15 @@ options: - error default: create_only version_added: 2.10.0 + restrict: + description: + - Restrict operation to entries matching the following criteria. + - This can be useful together with O(handle_absent_entries=remove) to operate on a subset of + the values. + - For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and + O(restrict[].values=input) to restrict operation to the input chain, and ignore the + forward and output chains. + version_added: 2.18.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -378,6 +388,23 @@ EXAMPLES = ''' out-interface: to-addresses: ~ '!to-ports': + +- name: Block all incoming connections + community.routeros.api_modify: + hostname: "{{ hostname }}" + password: "{{ password }}" + username: "{{ username }}" + path: ip firewall filter + handle_absent_entries: remove + handle_entries_content: remove_as_much_as_possible + restrict: + # Do not touch any chain except the input chain + - field: chain + values: + - input + data: + - action: drop + chain: input ''' RETURN = ''' @@ -434,6 +461,12 @@ from ansible_collections.community.routeros.plugins.module_utils._api_data impor split_path, ) +from ansible_collections.community.routeros.plugins.module_utils._api_helper import ( + restrict_argument_spec, + restrict_entry_accepted, + validate_and_prepare_restrict, +) + HAS_ORDEREDDICT = True try: from collections import OrderedDict @@ -699,18 +732,29 @@ def prepare_for_add(entry, path_info): return new_entry -def sync_list(module, api, path, path_info): +def remove_rejected(data, path_info, restrict_data): + return [ + entry for entry in data + if restrict_entry_accepted(entry, path_info, restrict_data) + ] + + +def sync_list(module, api, path, path_info, restrict_data): handle_absent_entries = module.params['handle_absent_entries'] handle_entries_content = module.params['handle_entries_content'] if handle_absent_entries == 'remove': if handle_entries_content == 'ignore': - module.fail_json('For this path, handle_absent_entries=remove cannot be combined with handle_entries_content=ignore') + module.fail_json( + msg='For this path, handle_absent_entries=remove cannot be combined with handle_entries_content=ignore' + ) stratify_keys = path_info.stratify_keys or () data = module.params['data'] stratified_data = defaultdict(list) for index, entry in enumerate(data): + if not restrict_entry_accepted(entry, path_info, restrict_data): + module.fail_json(msg='The element at index #{index} does not match `restrict`'.format(index=index + 1)) for stratify_key in stratify_keys: if stratify_key not in entry: module.fail_json( @@ -731,6 +775,7 @@ def sync_list(module, api, path, path_info): old_data = get_api_data(api_path, path_info) old_data = remove_dynamic(old_data) + old_data = remove_rejected(old_data, path_info, restrict_data) stratified_old_data = defaultdict(list) for index, entry in enumerate(old_data): sks = tuple(entry[stratify_key] for stratify_key in stratify_keys) @@ -843,6 +888,7 @@ def sync_list(module, api, path, path_info): # For sake of completeness, retrieve the full new data: if modify_list or create_list or reorder_list: new_data = remove_dynamic(get_api_data(api_path, path_info)) + new_data = remove_rejected(new_data, path_info, restrict_data) # Remove 'irrelevant' data for entry in old_data: @@ -869,7 +915,7 @@ def sync_list(module, api, path, path_info): ) -def sync_with_primary_keys(module, api, path, path_info): +def sync_with_primary_keys(module, api, path, path_info, restrict_data): primary_keys = path_info.primary_keys if path_info.fixed_entries: @@ -881,6 +927,8 @@ def sync_with_primary_keys(module, api, path, path_info): data = module.params['data'] new_data_by_key = OrderedDict() for index, entry in enumerate(data): + if not restrict_entry_accepted(entry, path_info, restrict_data): + module.fail_json(msg='The element at index #{index} does not match `restrict`'.format(index=index + 1)) for primary_key in primary_keys: if primary_key not in entry: module.fail_json( @@ -912,6 +960,7 @@ def sync_with_primary_keys(module, api, path, path_info): old_data = get_api_data(api_path, path_info) old_data = remove_dynamic(old_data) + old_data = remove_rejected(old_data, path_info, restrict_data) old_data_by_key = OrderedDict() id_by_key = {} for entry in old_data: @@ -1038,6 +1087,7 @@ def sync_with_primary_keys(module, api, path, path_info): # For sake of completeness, retrieve the full new data: if modify_list or create_list or reorder_list: new_data = remove_dynamic(get_api_data(api_path, path_info)) + new_data = remove_rejected(new_data, path_info, restrict_data) # Remove 'irrelevant' data for entry in old_data: @@ -1064,7 +1114,9 @@ def sync_with_primary_keys(module, api, path, path_info): ) -def sync_single_value(module, api, path, path_info): +def sync_single_value(module, api, path, path_info, restrict_data): + if module.params['restrict'] is not None: + module.fail_json(msg='The restrict option cannot be used with this path, since there is precisely one entry.') data = module.params['data'] if len(data) != 1: module.fail_json(msg='Data must be a list with exactly one element.') @@ -1162,6 +1214,7 @@ def main(): handle_write_only=dict(type='str', default='create_only', choices=['create_only', 'always_update', 'error']), ) module_args.update(api_argument_spec()) + module_args.update(restrict_argument_spec()) module = AnsibleModule( argument_spec=module_args, @@ -1193,7 +1246,9 @@ def main(): if path_info is None or backend is None: module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path))) - backend(module, api, path, path_info) + restrict_data = validate_and_prepare_restrict(module, path_info) + + backend(module, api, path, path_info, restrict_data) if __name__ == '__main__': diff --git a/tests/unit/plugins/module_utils/test__api_helper.py b/tests/unit/plugins/module_utils/test__api_helper.py new file mode 100644 index 0000000..b909f38 --- /dev/null +++ b/tests/unit/plugins/module_utils/test__api_helper.py @@ -0,0 +1,377 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Felix Fontein (@felixfontein) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import re +import sys + +import pytest + +from ansible_collections.community.routeros.plugins.module_utils._api_data import ( + PATHS, +) + +from ansible_collections.community.routeros.plugins.module_utils._api_helper import ( + _value_to_str, + _test_rule_except_invert, + validate_and_prepare_restrict, + restrict_entry_accepted, +) + + +VALUE_TO_STR = [ + (None, None), + ('', u''), + ('foo', u'foo'), + (True, u'true'), + (False, u'false'), + ([], u'[]'), + ({}, u'{}'), + (1, u'1'), + (-42, u'-42'), + (1.5, u'1.5'), + (1.0, u'1.0'), +] + + +@pytest.mark.parametrize("value, expected", VALUE_TO_STR) +def test_value_to_str(value, expected): + result = _value_to_str(value) + print(repr(result)) + assert result == expected + + +TEST_RULE_EXCEPT_INVERT = [ + ( + None, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + }, + False, + ), + ( + None, + { + 'field': u'foo', + 'match_disabled': True, + 'invert': False, + }, + True, + ), + ( + 1, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + 'values': [1], + }, + True, + ), + ( + 1, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + 'values': ['1'], + }, + False, + ), + ( + 1, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + 'regex': re.compile(u'^1$'), + 'regex_source': u'^1$', + }, + True, + ), + ( + 1.10, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + 'regex': re.compile(u'^1\\.1$'), + 'regex_source': u'^1\\.1$', + }, + True, + ), + ( + 10, + { + 'field': u'foo', + 'match_disabled': False, + 'invert': False, + 'regex': re.compile(u'^1$'), + 'regex_source': u'^1$', + }, + False, + ), +] + + +@pytest.mark.parametrize("value, rule, expected", TEST_RULE_EXCEPT_INVERT) +def test_rule_except_invert(value, rule, expected): + result = _test_rule_except_invert(value, rule) + print(repr(result)) + assert result == expected + + +_test_path = PATHS[('ip', 'firewall', 'filter')] +_test_path.provide_version('7.0') +TEST_PATH = _test_path.get_data() + + +class FailJsonExc(Exception): + def __init__(self, msg, kwargs): + self.msg = msg + self.kwargs = kwargs + + +class FakeModule(object): + def __init__(self, restrict_value): + self.params = { + 'restrict': restrict_value, + } + + def fail_json(self, msg, **kwargs): + raise FailJsonExc(msg, kwargs) + + +TEST_VALIDATE_AND_PREPARE_RESTRICT = [ + ( + [{ + 'field': u'chain', + 'match_disabled': False, + 'values': None, + 'regex': None, + 'invert': False, + }], + [{ + 'field': u'chain', + 'match_disabled': False, + 'invert': False, + }], + ), + ( + [{ + 'field': u'comment', + 'match_disabled': True, + 'values': None, + 'regex': None, + 'invert': False, + }], + [{ + 'field': u'comment', + 'match_disabled': True, + 'invert': False, + }], + ), + ( + [{ + 'field': u'comment', + 'match_disabled': False, + 'values': None, + 'regex': None, + 'invert': True, + }], + [{ + 'field': u'comment', + 'match_disabled': False, + 'invert': True, + }], + ), +] + +if sys.version_info >= (2, 7, 17): + # Somewhere between Python 2.7.15 (used by Ansible 3.9) and 2.7.17 (used by ansible-base 2.10) + # something changed with ``==`` for ``re.Pattern``, at least for some patterns + # (my guess is: for ``re.compile(u'')``) + TEST_VALIDATE_AND_PREPARE_RESTRICT.extend([ + ( + [ + { + 'field': u'comment', + 'match_disabled': False, + 'values': [], + 'regex': None, + 'invert': False, + }, + { + 'field': u'comment', + 'match_disabled': False, + 'values': [None, 1, 42.0, True, u'foo', [], {}], + 'regex': None, + 'invert': False, + }, + { + 'field': u'chain', + 'match_disabled': False, + 'values': None, + 'regex': u'', + 'invert': True, + }, + { + 'field': u'chain', + 'match_disabled': False, + 'values': None, + 'regex': u'foo', + 'invert': False, + }, + ], + [ + { + 'field': u'comment', + 'match_disabled': False, + 'invert': False, + 'values': [], + }, + { + 'field': u'comment', + 'match_disabled': False, + 'invert': False, + 'values': [None, 1, 42.0, True, u'foo', [], {}], + }, + { + 'field': u'chain', + 'match_disabled': False, + 'invert': True, + 'regex': re.compile(u''), + 'regex_source': u'', + }, + { + 'field': u'chain', + 'match_disabled': False, + 'invert': False, + 'regex': re.compile(u'foo'), + 'regex_source': u'foo', + }, + ], + ), + ]) + + +@pytest.mark.parametrize("restrict_value, expected", TEST_VALIDATE_AND_PREPARE_RESTRICT) +def test_validate_and_prepare_restrict(restrict_value, expected): + fake_module = FakeModule(restrict_value) + result = validate_and_prepare_restrict(fake_module, TEST_PATH) + print(repr(result)) + assert result == expected + + +TEST_VALIDATE_AND_PREPARE_RESTRICT_FAIL = [ + ( + [{ + 'field': u'!foo', + 'match_disabled': False, + 'values': None, + 'regex': None, + 'invert': False, + }], + ['restrict: the field name "!foo" must not start with "!"'], + ), + ( + [{ + 'field': u'foo', + 'match_disabled': False, + 'values': None, + 'regex': None, + 'invert': False, + }], + ['restrict: the field "foo" does not exist for this path'], + ), + ( + [{ + 'field': u'chain', + 'match_disabled': False, + 'values': None, + 'regex': u'(', + 'invert': False, + }], + [ + 'restrict: invalid regular expression "(": missing ), unterminated subpattern at position 0', + 'restrict: invalid regular expression "(": unbalanced parenthesis', + ] + ), +] + + +@pytest.mark.parametrize("restrict_value, expected", TEST_VALIDATE_AND_PREPARE_RESTRICT_FAIL) +def test_validate_and_prepare_restrict_fail(restrict_value, expected): + fake_module = FakeModule(restrict_value) + with pytest.raises(FailJsonExc) as exc: + validate_and_prepare_restrict(fake_module, TEST_PATH) + print(repr(exc.value.msg)) + assert exc.value.msg in expected + + +TEST_RESTRICT_ENTRY_ACCEPTED = [ + ( + { + 'chain': 'input', + }, + [ + { + 'field': u'chain', + 'match_disabled': False, + 'invert': False, + }, + ], + False, + ), + ( + { + 'chain': 'input', + }, + [ + { + 'field': u'chain', + 'match_disabled': False, + 'invert': True, + }, + ], + True, + ), + ( + { + 'comment': 'foo', + }, + [ + { + 'field': u'comment', + 'match_disabled': True, + 'invert': False, + }, + ], + False, + ), + ( + {}, + [ + { + 'field': u'comment', + 'match_disabled': True, + 'invert': False, + }, + ], + True, + ), +] + + +@pytest.mark.parametrize("entry, restrict_data, expected", TEST_RESTRICT_ENTRY_ACCEPTED) +def test_restrict_entry_accepted(entry, restrict_data, expected): + result = restrict_entry_accepted(entry, TEST_PATH, restrict_data) + print(repr(result)) + assert result == expected diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 3564668..1c9d014 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -822,3 +822,169 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'comment': 'foo', }, ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_restrict_1(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + 'dynamic': False, + '.id': '*1', + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': False, + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'omit', + 'restrict': [], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + '.id': '*1', + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_restrict_2(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + 'dynamic': False, + '.id': '*1', + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': False, + }, + { + 'chain': 'input', + 'action': 'drop', + 'dynamic': False, + '.id': '*3', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'omit', + 'restrict': [{ + 'field': 'chain', + 'values': ['forward'], + }], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + }, + ]) + + @patch('ansible_collections.community.routeros.plugins.modules.api_info.compose_api_path') + def test_restrict_3(self, mock_compose_api_path): + mock_compose_api_path.return_value = [ + { + 'chain': 'input', + 'in-interface-list': 'LAN', + 'dynamic': False, + '.id': '*1', + }, + { + 'chain': 'forward', + 'action': 'drop', + 'in-interface': 'sfp1', + '.id': '*2', + 'dynamic': False, + }, + { + 'chain': 'input', + 'action': 'drop', + 'dynamic': False, + '.id': '*3', + }, + { + 'chain': 'input', + 'action': 'drop', + 'comment': 'Foo', + 'dynamic': False, + '.id': '*4', + }, + { + 'chain': 'input', + 'action': 'drop', + 'comment': 'Bar', + 'dynamic': False, + '.id': '*5', + }, + ] + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip firewall filter', + 'handle_disabled': 'omit', + 'restrict': [ + { + 'field': 'chain', + 'values': ['input', 'foobar'], + }, + { + 'field': 'action', + 'values': ['drop', 42], + }, + { + 'field': 'comment', + 'values': [None, 'Foo'], + }, + ], + }) + set_module_args(args) + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['result'], [ + { + 'chain': 'input', + 'action': 'drop', + '.id': '*3', + }, + { + 'chain': 'input', + 'action': 'drop', + 'comment': 'Foo', + '.id': '*4', + }, + ]) From 1a2faec1c02400e5fd5959e231f64cc9410a86a9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 12 Aug 2024 21:20:16 +0200 Subject: [PATCH 262/365] Release 2.18.0. --- CHANGELOG.md | 318 ++++++++++-------- CHANGELOG.rst | 29 ++ changelogs/changelog.yaml | 40 +++ changelogs/fragments/2.18.0.yml | 1 - .../300-add-ip-dhcp-server-matcher.yml | 2 - .../300-set-ip-dhcp-option-force-default.yml | 2 - .../fragments/302-ospf-static-neighbor.yml | 2 - .../fragments/303-add-ipv6-nd-prefix.yml | 2 - .../304-wireguard-name-responder.yml | 2 - changelogs/fragments/305-api-restrict.yml | 3 - .../fragments/306-ingress-filtering-ros6.yml | 2 - .../fragments/deprecate-eol-ansible-core.yml | 5 - 12 files changed, 245 insertions(+), 163 deletions(-) delete mode 100644 changelogs/fragments/2.18.0.yml delete mode 100644 changelogs/fragments/300-add-ip-dhcp-server-matcher.yml delete mode 100644 changelogs/fragments/300-set-ip-dhcp-option-force-default.yml delete mode 100644 changelogs/fragments/302-ospf-static-neighbor.yml delete mode 100644 changelogs/fragments/303-add-ipv6-nd-prefix.yml delete mode 100644 changelogs/fragments/304-wireguard-name-responder.yml delete mode 100644 changelogs/fragments/305-api-restrict.yml delete mode 100644 changelogs/fragments/306-ingress-filtering-ros6.yml delete mode 100644 changelogs/fragments/deprecate-eol-ansible-core.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e78ef2..0aed643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,115 +2,120 @@ **Topics** -- v2\.17\.0 +- v2\.18\.0 - Release Summary - Minor Changes -- v2\.16\.0 + - Deprecated Features + - Bugfixes +- v2\.17\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - Minor Changes - Bugfixes - - Known Issues -- v2\.3\.1 +- v2\.4\.0 - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - Minor Changes - Bugfixes -- v2\.2\.1 + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary - Bugfixes - - New Modules -- v2\.1\.0 +- v2\.2\.0 - Release Summary - Minor Changes - Bugfixes - - New Modules -- v2\.0\.0 + - New Modules +- v2\.1\.0 - Release Summary - Minor Changes - - Breaking Changes / Porting Guide - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 - - Release Summary - Bugfixes -- v1\.0\.0 +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary - - Minor Changes + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes - -## v2\.17\.0 + +## v2\.18\.0 ### Release Summary @@ -120,12 +125,26 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. -* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. -* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. +* api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. +* api\_info\, api\_modify \- add support for the ip dhcp\-server matcher path \([https\://github\.com/ansible\-collections/community\.routeros/pull/300](https\://github\.com/ansible\-collections/community\.routeros/pull/300)\)\. +* api\_info\, api\_modify \- add support for the ipv6 nd prefix path \([https\://github\.com/ansible\-collections/community\.routeros/pull/303](https\://github\.com/ansible\-collections/community\.routeros/pull/303)\)\. +* api\_info\, api\_modify \- add support for the name and is\-responder properties under the interface wireguard peers path introduced in RouterOS 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/pull/304](https\://github\.com/ansible\-collections/community\.routeros/pull/304)\)\. +* api\_info\, api\_modify \- add support for the routing ospf static\-neighbor path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/302](https\://github\.com/ansible\-collections/community\.routeros/pull/302)\)\. +* api\_info\, api\_modify \- set default for force in ip dhcp\-server option to an explicit false \([https\://github\.com/ansible\-collections/community\.routeros/pull/300](https\://github\.com/ansible\-collections/community\.routeros/pull/300)\)\. +* api\_modify \- allow to restrict what is updated by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. - -## v2\.16\.0 + +### Deprecated Features + +* The collection deprecates support for all Ansible/ansible\-base/ansible\-core versions that are currently End of Life\, [according to the ansible\-core support matrix](https\://docs\.ansible\.com/ansible\-core/devel/reference\_appendices/release\_and\_maintenance\.html\#ansible\-core\-support\-matrix)\. This means that the next major release of the collection will no longer support Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. + + +### Bugfixes + +* api\_modify\, api\_info \- change the default of ingress\-filtering in paths interface bridge and interface bridge port back to false for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. + + +## v2\.17\.0 ### Release Summary @@ -135,11 +154,12 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. -* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. +* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. +* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. +* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -149,6 +169,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -163,12 +197,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -178,18 +212,18 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + ### Bugfixes * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. @@ -197,12 +231,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -216,12 +250,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -236,12 +270,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -265,7 +299,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -273,18 +307,18 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -292,7 +326,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -313,19 +347,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -334,35 +355,23 @@ Bugfix release\. ### Bugfixes -* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - -## v2\.8\.0 + +## v2\.8\.1 ### Release Summary -Bugfix and feature release\. - - -### Minor Changes - -* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. -* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. -* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. -* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. +Bugfix release\. ### Bugfixes -* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. - -## v2\.7\.0 + +## v2\.8\.0 ### Release Summary @@ -372,28 +381,53 @@ Bugfix and feature release\. ### Minor Changes -* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. ### Bugfixes +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -402,17 +436,17 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -420,12 +454,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -446,7 +480,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -464,7 +498,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -477,19 +511,19 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -497,12 +531,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -511,17 +545,17 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -535,12 +569,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -549,7 +583,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -564,12 +598,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -583,7 +617,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -605,12 +639,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -618,7 +652,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -626,12 +660,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -640,12 +674,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -653,12 +687,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -666,12 +700,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -679,12 +713,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 011644d..1086c30 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,35 @@ Community RouterOS Release Notes .. contents:: Topics +v2.18.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info - allow to restrict the output by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305). +- api_info, api_modify - add support for the ``ip dhcp-server matcher`` path (https://github.com/ansible-collections/community.routeros/pull/300). +- api_info, api_modify - add support for the ``ipv6 nd prefix`` path (https://github.com/ansible-collections/community.routeros/pull/303). +- api_info, api_modify - add support for the ``name`` and ``is-responder`` properties under the ``interface wireguard peers`` path introduced in RouterOS 7.15 (https://github.com/ansible-collections/community.routeros/pull/304). +- api_info, api_modify - add support for the ``routing ospf static-neighbor`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/302). +- api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/pull/300). +- api_modify - allow to restrict what is updated by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305). + +Deprecated Features +------------------- + +- The collection deprecates support for all Ansible/ansible-base/ansible-core versions that are currently End of Life, `according to the ansible-core support matrix `__. This means that the next major release of the collection will no longer support Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14. + +Bugfixes +-------- + +- api_modify, api_info - change the default of ``ingress-filtering`` in paths ``interface bridge`` and ``interface bridge port`` back to ``false`` for RouterOS before version 7 (https://github.com/ansible-collections/community.routeros/pull/305). + v2.17.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 26cde43..ec8343e 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -714,3 +714,43 @@ releases: - 295-add_system_resource_irq_rps_path.yml - 297-add-ip-ssh-host-key-type.yml release_date: '2024-07-09' + 2.18.0: + changes: + bugfixes: + - api_modify, api_info - change the default of ``ingress-filtering`` in paths + ``interface bridge`` and ``interface bridge port`` back to ``false`` for + RouterOS before version 7 (https://github.com/ansible-collections/community.routeros/pull/305). + deprecated_features: + - The collection deprecates support for all Ansible/ansible-base/ansible-core + versions that are currently End of Life, `according to the ansible-core + support matrix `__. + This means that the next major release of the collection will no longer + support Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core + 2.12, ansible-core 2.13, and ansible-core 2.14. + minor_changes: + - api_info - allow to restrict the output by limiting fields to specific values + with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305). + - api_info, api_modify - add support for the ``ip dhcp-server matcher`` path + (https://github.com/ansible-collections/community.routeros/pull/300). + - api_info, api_modify - add support for the ``ipv6 nd prefix`` path (https://github.com/ansible-collections/community.routeros/pull/303). + - api_info, api_modify - add support for the ``name`` and ``is-responder`` + properties under the ``interface wireguard peers`` path introduced in RouterOS + 7.15 (https://github.com/ansible-collections/community.routeros/pull/304). + - api_info, api_modify - add support for the ``routing ospf static-neighbor`` + path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/302). + - api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` + to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/pull/300). + - api_modify - allow to restrict what is updated by limiting fields to specific + values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305). + release_summary: Feature release. + fragments: + - 2.18.0.yml + - 300-add-ip-dhcp-server-matcher.yml + - 300-set-ip-dhcp-option-force-default.yml + - 302-ospf-static-neighbor.yml + - 303-add-ipv6-nd-prefix.yml + - 304-wireguard-name-responder.yml + - 305-api-restrict.yml + - 306-ingress-filtering-ros6.yml + - deprecate-eol-ansible-core.yml + release_date: '2024-08-12' diff --git a/changelogs/fragments/2.18.0.yml b/changelogs/fragments/2.18.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/2.18.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml b/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml deleted file mode 100644 index c80a3a3..0000000 --- a/changelogs/fragments/300-add-ip-dhcp-server-matcher.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ip dhcp-server matcher`` path (https://github.com/ansible-collections/community.routeros/pull/300). diff --git a/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml b/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml deleted file mode 100644 index 1f9585d..0000000 --- a/changelogs/fragments/300-set-ip-dhcp-option-force-default.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - set default for ``force`` in ``ip dhcp-server option`` to an explicit ``false`` (https://github.com/ansible-collections/community.routeros/pull/300). diff --git a/changelogs/fragments/302-ospf-static-neighbor.yml b/changelogs/fragments/302-ospf-static-neighbor.yml deleted file mode 100644 index 5f93ec4..0000000 --- a/changelogs/fragments/302-ospf-static-neighbor.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing ospf static-neighbor`` path in RouterOS 7 (https://github.com/ansible-collections/community.routeros/pull/302). diff --git a/changelogs/fragments/303-add-ipv6-nd-prefix.yml b/changelogs/fragments/303-add-ipv6-nd-prefix.yml deleted file mode 100644 index b28915a..0000000 --- a/changelogs/fragments/303-add-ipv6-nd-prefix.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ipv6 nd prefix`` path (https://github.com/ansible-collections/community.routeros/pull/303). diff --git a/changelogs/fragments/304-wireguard-name-responder.yml b/changelogs/fragments/304-wireguard-name-responder.yml deleted file mode 100644 index e333082..0000000 --- a/changelogs/fragments/304-wireguard-name-responder.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``name`` and ``is-responder`` properties under the ``interface wireguard peers`` path introduced in RouterOS 7.15 (https://github.com/ansible-collections/community.routeros/pull/304). diff --git a/changelogs/fragments/305-api-restrict.yml b/changelogs/fragments/305-api-restrict.yml deleted file mode 100644 index 3b737ea..0000000 --- a/changelogs/fragments/305-api-restrict.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - "api_info - allow to restrict the output by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305)." - - "api_modify - allow to restrict what is updated by limiting fields to specific values with the new ``restrict`` option (https://github.com/ansible-collections/community.routeros/pull/305)." diff --git a/changelogs/fragments/306-ingress-filtering-ros6.yml b/changelogs/fragments/306-ingress-filtering-ros6.yml deleted file mode 100644 index fc9ea73..0000000 --- a/changelogs/fragments/306-ingress-filtering-ros6.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "api_modify, api_info - change the default of ``ingress-filtering`` in paths ``interface bridge`` and ``interface bridge port`` back to ``false`` for RouterOS before version 7 (https://github.com/ansible-collections/community.routeros/pull/305)." diff --git a/changelogs/fragments/deprecate-eol-ansible-core.yml b/changelogs/fragments/deprecate-eol-ansible-core.yml deleted file mode 100644 index 630f7c9..0000000 --- a/changelogs/fragments/deprecate-eol-ansible-core.yml +++ /dev/null @@ -1,5 +0,0 @@ -deprecated_features: - - "The collection deprecates support for all Ansible/ansible-base/ansible-core versions that are currently End of Life, - `according to the ansible-core support matrix `__. - This means that the next major release of the collection will no longer support Ansible 2.9, ansible-base 2.10, ansible-core 2.11, - ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14." From 5fb0bf021259dd0169c4dc2aac500e2b4af39925 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 12 Aug 2024 21:35:45 +0200 Subject: [PATCH 263/365] Improve RouterOS link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ef42b5..cc62f4c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.routeros)](https://codecov.io/gh/ansible-collections/community.routeros) [![REUSE status](https://api.reuse.software/badge/github.com/ansible-collections/community.routeros)](https://api.reuse.software/info/github.com/ansible-collections/community.routeros) -Provides modules for [Ansible](https://www.ansible.com/community) to manage [MikroTik RouterOS](http://www.mikrotik-routeros.net/routeros.aspx) instances. +Provides modules for [Ansible](https://www.ansible.com/community) to manage [MikroTik RouterOS](https://mikrotik.com/software) instances. You can find [documentation for the modules and plugins in this collection here](https://docs.ansible.com/ansible/devel/collections/community/routeros/). From b4ea8b2fe77408138adf7c84671cc81363a468ec Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 15 Aug 2024 12:12:25 +0200 Subject: [PATCH 264/365] Add support for the "routing igmp-proxy" path (#309) Upstream documentation: https://help.mikrotik.com/docs/display/ROS/IGMP+Proxy --- changelogs/fragments/309-add-igmp-proxy.yml | 2 ++ plugins/module_utils/_api_data.py | 25 +++++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 31 insertions(+) create mode 100644 changelogs/fragments/309-add-igmp-proxy.yml diff --git a/changelogs/fragments/309-add-igmp-proxy.yml b/changelogs/fragments/309-add-igmp-proxy.yml new file mode 100644 index 0000000..540310a --- /dev/null +++ b/changelogs/fragments/309-add-igmp-proxy.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing igmp-proxy`` path (https://github.com/ansible-collections/community.routeros/pull/309). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 478cd2e..ebb9da5 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3942,6 +3942,31 @@ PATHS = { }, ), ), + ('routing', 'igmp-proxy'): APIData( + unversioned=VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'query-interval': KeyInfo(), + 'query-response-interval': KeyInfo(), + 'quick-leave': KeyInfo(default=False), + }, + ), + ), + ('routing', 'igmp-proxy', 'interface'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('interface', ), + fields={ + 'alternative-subnets': KeyInfo(default=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(), + 'threshold': KeyInfo(), + 'upstream': KeyInfo(default=False), + }, + ), + ), ('routing', 'bfd', 'interface'): APIData( unversioned=VersionedAPIData( unknown_mechanism=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 24fd8fe..7110cde 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -206,6 +206,8 @@ options: - routing filter rule - routing filter select-rule - routing id + - routing igmp-proxy + - routing igmp-proxy interface - routing mme - routing ospf area - routing ospf area range diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index a2a2c10..e352552 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -215,6 +215,8 @@ options: - routing filter rule - routing filter select-rule - routing id + - routing igmp-proxy + - routing igmp-proxy interface - routing mme - routing ospf area - routing ospf area range From 274e249f26fa50f7fca8658312c6adbd0453e689 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 15 Aug 2024 21:40:37 +0200 Subject: [PATCH 265/365] Improve communication link description. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc62f4c..1bfd656 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you encounter abusive behavior violating the [Ansible Code of Conduct](https: ## Communication * Join the Ansible forum: - * [Get Help](https://forum.ansible.com/c/help/6): get help or help others. This is for questions about modules or plugins in the collection. + * [Get Help](https://forum.ansible.com/c/help/6): get help or help others.Please add appropriate tags if you start new discussions, for example the `routeros` tag. * [Posts tagged with 'routeros'](https://forum.ansible.com/tag/routeros): subscribe to participate in RouterOS related conversations. * [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts. * [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events. From 6c2101d4d8c2c25c01ffdf6aecd51c940231c2e6 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 22 Aug 2024 08:57:28 +0200 Subject: [PATCH 266/365] Add support for the "ip dns adlist" path (#310) Upstream documentation: https://help.mikrotik.com/docs/display/ROS/DNS#DNS-Adlist --- changelogs/fragments/310-add-ip-dns-adlist.yml | 2 ++ plugins/module_utils/_api_data.py | 16 ++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/310-add-ip-dns-adlist.yml diff --git a/changelogs/fragments/310-add-ip-dns-adlist.yml b/changelogs/fragments/310-add-ip-dns-adlist.yml new file mode 100644 index 0000000..3b96d8f --- /dev/null +++ b/changelogs/fragments/310-add-ip-dns-adlist.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ip dns adlist`` path implemented by RouterOS 7.15 and newer (https://github.com/ansible-collections/community.routeros/pull/310). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ebb9da5..a70cb2c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2818,6 +2818,22 @@ PATHS = { }, ), ), + ('ip', 'dns', 'adlist'): APIData( + versioned=[ + ('7.15', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'file': KeyInfo(default=''), + 'match-count': KeyInfo(read_only=True), + 'name-count': KeyInfo(read_only=True), + 'ssl-verify': KeyInfo(default=True), + 'url': KeyInfo(default=''), + }, + )), + ], + ), ('ip', 'dns', 'static'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 7110cde..296059d 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -131,6 +131,7 @@ options: - ip dhcp-server option - ip dhcp-server option sets - ip dns + - ip dns adlist - ip dns static - ip firewall address-list - ip firewall connection tracking diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index e352552..3261f5b 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -140,6 +140,7 @@ options: - ip dhcp-server option - ip dhcp-server option sets - ip dns + - ip dns adlist - ip dns static - ip firewall address-list - ip firewall connection tracking From 8158d90d79ae2bfacf24f6536c93468c64bd6a13 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 8 Sep 2024 16:16:27 +0200 Subject: [PATCH 267/365] Remove link to Google Groups mailing list. (#314) Ref: https://groups.google.com/g/ansible-project/c/B0oKR0aQqXs --- docs/docsite/links.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/docsite/links.yml b/docs/docsite/links.yml index 9324e87..0c68c84 100644 --- a/docs/docsite/links.yml +++ b/docs/docsite/links.yml @@ -24,9 +24,6 @@ communication: - topic: General usage and support questions network: Libera channel: '#ansible' - mailing_lists: - - topic: Ansible Project List - url: https://groups.google.com/g/ansible-project forums: - topic: "Ansible Forum: General usage and support questions" # The following URL directly points to the "Get Help" section From 89b34bdd7970170491931aba124b21af0a8904cd Mon Sep 17 00:00:00 2001 From: Tim de Boer Date: Mon, 9 Sep 2024 22:57:25 +0200 Subject: [PATCH 268/365] Added support for 'routing filter num-list' (#313) * Added support for 'routing filter num-list' * Added support for 'routing filter num-list', changelog * Added support for 'routing filter num-list', changelog --- .../fragments/313-add-routing-filter-num-list.yml | 2 ++ plugins/module_utils/_api_data.py | 13 +++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 17 insertions(+) create mode 100644 changelogs/fragments/313-add-routing-filter-num-list.yml diff --git a/changelogs/fragments/313-add-routing-filter-num-list.yml b/changelogs/fragments/313-add-routing-filter-num-list.yml new file mode 100644 index 0000000..5e12ed4 --- /dev/null +++ b/changelogs/fragments/313-add-routing-filter-num-list.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing filter num-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/313). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index a70cb2c..d6e767b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -844,6 +844,19 @@ PATHS = { )), ], ), + ('routing', 'filter', 'num-list'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'list': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'range': KeyInfo(can_disable=True), + }, + )), + ], + ), ('routing', 'filter', 'rule'): APIData( versioned=[ ('7', '>=', VersionedAPIData( diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 296059d..a1d979f 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -204,6 +204,7 @@ options: - routing bgp peer - routing bgp template - routing filter + - routing filter num-list - routing filter rule - routing filter select-rule - routing id diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 3261f5b..24732a1 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -213,6 +213,7 @@ options: - routing bgp peer - routing bgp template - routing filter + - routing filter num-list - routing filter rule - routing filter select-rule - routing id From 1942b3ddbb1776c70186f9a088f72934dc3d7689 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 9 Sep 2024 22:57:41 +0200 Subject: [PATCH 269/365] Support "mld-version" and "multicast-querier" on bridge interfaces (#315) Signed-off-by: Michael Hanselmann --- .../fragments/315-bridge-mld-version-multicast-querier.yml | 2 ++ plugins/module_utils/_api_data.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/315-bridge-mld-version-multicast-querier.yml diff --git a/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml b/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml new file mode 100644 index 0000000..0a8e373 --- /dev/null +++ b/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``mld-version`` and ``multicast-querier`` properties in ``interface bridge`` (https://github.com/ansible-collections/community.routeros/pull/315). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d6e767b..0189145 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -274,11 +274,13 @@ PATHS = { 'disabled': KeyInfo(default=False), 'ether-type': KeyInfo(default='0x8100'), 'fast-forward': KeyInfo(default=True), - 'frame-types': KeyInfo(default='admit-all'), 'forward-delay': KeyInfo(default='15s'), + 'frame-types': KeyInfo(default='admit-all'), 'igmp-snooping': KeyInfo(default=False), 'max-message-age': KeyInfo(default='20s'), + 'mld-version': KeyInfo(default=1), 'mtu': KeyInfo(default='auto'), + 'multicast-querier': KeyInfo(default=False), 'name': KeyInfo(), 'priority': KeyInfo(default='0x8000'), 'protocol-mode': KeyInfo(default='rstp'), From 136250a802fcb98611f94c6fc6a64bff0c866449 Mon Sep 17 00:00:00 2001 From: Tr4sK Date: Tue, 10 Sep 2024 09:08:10 +0200 Subject: [PATCH 270/365] Add default to snmp community api_data (#311) * Add default to snmp community api_data * Add changelog fragment * fix typo * suggestion from felixfontein * suggestion from felixfontein * Apply suggestions from code review --------- Co-authored-by: Felix Fontein --- changelogs/fragments/311-add-defaults-fields-snmp-community.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/311-add-defaults-fields-snmp-community.yml diff --git a/changelogs/fragments/311-add-defaults-fields-snmp-community.yml b/changelogs/fragments/311-add-defaults-fields-snmp-community.yml new file mode 100644 index 0000000..ff45330 --- /dev/null +++ b/changelogs/fragments/311-add-defaults-fields-snmp-community.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - add read-only ``default`` field to ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/311). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0189145..05e1409 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1101,6 +1101,7 @@ PATHS = { fully_understood=True, primary_keys=('name', ), fields={ + 'default': KeyInfo(read_only=True), 'addresses': KeyInfo(default='::/0'), 'authentication-password': KeyInfo(default=''), 'authentication-protocol': KeyInfo(default='MD5'), From fed11d36f7ad616ffc065e0f8226a37414a4a65f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 10 Sep 2024 09:37:29 +0200 Subject: [PATCH 271/365] Prepare 2.19.0. --- changelogs/fragments/2.19.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.19.0.yml diff --git a/changelogs/fragments/2.19.0.yml b/changelogs/fragments/2.19.0.yml new file mode 100644 index 0000000..63e0654 --- /dev/null +++ b/changelogs/fragments/2.19.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index cbec7c0..2c9fe9a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.18.0 +version: 2.19.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From ff7e6162d7eab3b7a45ab981b6fde9765efc047e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 10 Sep 2024 09:43:54 +0200 Subject: [PATCH 272/365] Release 2.19.0. --- CHANGELOG.md | 214 ++++++++++-------- CHANGELOG.rst | 17 ++ changelogs/changelog.yaml | 21 ++ changelogs/fragments/2.19.0.yml | 1 - changelogs/fragments/309-add-igmp-proxy.yml | 2 - .../fragments/310-add-ip-dns-adlist.yml | 2 - ...311-add-defaults-fields-snmp-community.yml | 2 - .../313-add-routing-filter-num-list.yml | 2 - ...5-bridge-mld-version-multicast-querier.yml | 2 - 9 files changed, 155 insertions(+), 108 deletions(-) delete mode 100644 changelogs/fragments/2.19.0.yml delete mode 100644 changelogs/fragments/309-add-igmp-proxy.yml delete mode 100644 changelogs/fragments/310-add-ip-dns-adlist.yml delete mode 100644 changelogs/fragments/311-add-defaults-fields-snmp-community.yml delete mode 100644 changelogs/fragments/313-add-routing-filter-num-list.yml delete mode 100644 changelogs/fragments/315-bridge-mld-version-multicast-querier.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aed643..13c36e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,120 +2,123 @@ **Topics** -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v2\.18\.0 + +## v2\.19\.0 ### Release Summary @@ -125,6 +128,23 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. +* api\_info\, api\_modify \- add support for the mld\-version and multicast\-querier properties in interface bridge \([https\://github\.com/ansible\-collections/community\.routeros/pull/315](https\://github\.com/ansible\-collections/community\.routeros/pull/315)\)\. +* api\_info\, api\_modify \- add support for the routing filter num\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/313](https\://github\.com/ansible\-collections/community\.routeros/pull/313)\)\. +* api\_info\, api\_modify \- add support for the routing igmp\-proxy path \([https\://github\.com/ansible\-collections/community\.routeros/pull/309](https\://github\.com/ansible\-collections/community\.routeros/pull/309)\)\. +* api\_modify\, api\_info \- add read\-only default field to snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/311](https\://github\.com/ansible\-collections/community\.routeros/pull/311)\)\. + + +## v2\.18\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. * api\_info\, api\_modify \- add support for the ip dhcp\-server matcher path \([https\://github\.com/ansible\-collections/community\.routeros/pull/300](https\://github\.com/ansible\-collections/community\.routeros/pull/300)\)\. * api\_info\, api\_modify \- add support for the ipv6 nd prefix path \([https\://github\.com/ansible\-collections/community\.routeros/pull/303](https\://github\.com/ansible\-collections/community\.routeros/pull/303)\)\. @@ -146,12 +166,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -161,12 +181,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -175,12 +195,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -197,12 +217,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -212,12 +232,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -231,12 +251,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -250,12 +270,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -270,12 +290,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -307,12 +327,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -326,7 +346,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -347,7 +367,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -360,7 +380,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -373,12 +393,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -398,12 +418,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -416,12 +436,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -436,12 +456,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -454,12 +474,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -498,7 +518,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -511,12 +531,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -531,7 +551,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -545,12 +565,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -569,12 +589,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -598,12 +618,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -639,12 +659,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -660,12 +680,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -674,7 +694,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -687,7 +707,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -700,7 +720,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -713,12 +733,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1086c30..21df114 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,23 @@ Community RouterOS Release Notes .. contents:: Topics +v2.19.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add support for the ``ip dns adlist`` path implemented by RouterOS 7.15 and newer (https://github.com/ansible-collections/community.routeros/pull/310). +- api_info, api_modify - add support for the ``mld-version`` and ``multicast-querier`` properties in ``interface bridge`` (https://github.com/ansible-collections/community.routeros/pull/315). +- api_info, api_modify - add support for the ``routing filter num-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/313). +- api_info, api_modify - add support for the ``routing igmp-proxy`` path (https://github.com/ansible-collections/community.routeros/pull/309). +- api_modify, api_info - add read-only ``default`` field to ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/311). + v2.18.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index ec8343e..3c64ad3 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -754,3 +754,24 @@ releases: - 306-ingress-filtering-ros6.yml - deprecate-eol-ansible-core.yml release_date: '2024-08-12' + 2.19.0: + changes: + minor_changes: + - api_info, api_modify - add support for the ``ip dns adlist`` path implemented + by RouterOS 7.15 and newer (https://github.com/ansible-collections/community.routeros/pull/310). + - api_info, api_modify - add support for the ``mld-version`` and ``multicast-querier`` + properties in ``interface bridge`` (https://github.com/ansible-collections/community.routeros/pull/315). + - api_info, api_modify - add support for the ``routing filter num-list`` path + implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/313). + - api_info, api_modify - add support for the ``routing igmp-proxy`` path (https://github.com/ansible-collections/community.routeros/pull/309). + - api_modify, api_info - add read-only ``default`` field to ``snmp community`` + (https://github.com/ansible-collections/community.routeros/pull/311). + release_summary: Feature release. + fragments: + - 2.19.0.yml + - 309-add-igmp-proxy.yml + - 310-add-ip-dns-adlist.yml + - 311-add-defaults-fields-snmp-community.yml + - 313-add-routing-filter-num-list.yml + - 315-bridge-mld-version-multicast-querier.yml + release_date: '2024-09-10' diff --git a/changelogs/fragments/2.19.0.yml b/changelogs/fragments/2.19.0.yml deleted file mode 100644 index 63e0654..0000000 --- a/changelogs/fragments/2.19.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. \ No newline at end of file diff --git a/changelogs/fragments/309-add-igmp-proxy.yml b/changelogs/fragments/309-add-igmp-proxy.yml deleted file mode 100644 index 540310a..0000000 --- a/changelogs/fragments/309-add-igmp-proxy.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing igmp-proxy`` path (https://github.com/ansible-collections/community.routeros/pull/309). diff --git a/changelogs/fragments/310-add-ip-dns-adlist.yml b/changelogs/fragments/310-add-ip-dns-adlist.yml deleted file mode 100644 index 3b96d8f..0000000 --- a/changelogs/fragments/310-add-ip-dns-adlist.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ip dns adlist`` path implemented by RouterOS 7.15 and newer (https://github.com/ansible-collections/community.routeros/pull/310). diff --git a/changelogs/fragments/311-add-defaults-fields-snmp-community.yml b/changelogs/fragments/311-add-defaults-fields-snmp-community.yml deleted file mode 100644 index ff45330..0000000 --- a/changelogs/fragments/311-add-defaults-fields-snmp-community.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_modify, api_info - add read-only ``default`` field to ``snmp community`` (https://github.com/ansible-collections/community.routeros/pull/311). diff --git a/changelogs/fragments/313-add-routing-filter-num-list.yml b/changelogs/fragments/313-add-routing-filter-num-list.yml deleted file mode 100644 index 5e12ed4..0000000 --- a/changelogs/fragments/313-add-routing-filter-num-list.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing filter num-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/313). diff --git a/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml b/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml deleted file mode 100644 index 0a8e373..0000000 --- a/changelogs/fragments/315-bridge-mld-version-multicast-querier.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``mld-version`` and ``multicast-querier`` properties in ``interface bridge`` (https://github.com/ansible-collections/community.routeros/pull/315). From c864078549e89ff49cadb647739dc756bf57a2f8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 24 Sep 2024 13:47:53 +0300 Subject: [PATCH 273/365] Add stable-2.18 to CI. (#317) --- .github/workflows/ansible-test.yml | 7 ++++++- README.md | 2 +- tests/sanity/ignore-2.19.txt | 2 ++ tests/sanity/ignore-2.19.txt.license | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tests/sanity/ignore-2.19.txt create mode 100644 tests/sanity/ignore-2.19.txt.license diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index fa62419..ad01212 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -35,6 +35,7 @@ jobs: - stable-2.15 - stable-2.16 - stable-2.17 + - stable-2.18 - devel # Ansible-test on various stable branches does not yet work well with cgroups v2. # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 @@ -83,6 +84,7 @@ jobs: - stable-2.15 - stable-2.16 - stable-2.17 + - stable-2.18 - devel steps: @@ -151,7 +153,10 @@ jobs: python: "3.10" # 2.17 - ansible: stable-2.17 - python: "3.12" + python: "3.7" + # 2.18 + - ansible: stable-2.18 + python: "3.8" steps: - name: >- diff --git a/README.md b/README.md index 1bfd656..a773b72 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ For more information about communication, see the [Ansible communication guide]( ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, and ansible-core 2.17 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, and ansible-core 2.18 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. ## External requirements diff --git a/tests/sanity/ignore-2.19.txt b/tests/sanity/ignore-2.19.txt new file mode 100644 index 0000000..0a5234b --- /dev/null +++ b/tests/sanity/ignore-2.19.txt @@ -0,0 +1,2 @@ +update-docs.py shebang +tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 diff --git a/tests/sanity/ignore-2.19.txt.license b/tests/sanity/ignore-2.19.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.19.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From 5adc664b04ae13c89648cb8fd2e3c1f646083c80 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 10 Oct 2024 21:43:30 +0200 Subject: [PATCH 274/365] Support DHCP matching type added in RouterOS 7.16 (#321) --- changelogs/fragments/321-dhcp-server-matcher-matching-type.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/321-dhcp-server-matcher-matching-type.yml diff --git a/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml b/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml new file mode 100644 index 0000000..78b8779 --- /dev/null +++ b/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``matching-type`` property in ``ip dhcp-server matcher`` introduced by RouterOS 7.16 (https://github.com/ansible-collections/community.routeros/pull/321). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 05e1409..ae47274 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2798,6 +2798,9 @@ PATHS = { ('7.4', '>=', VersionedAPIData( fully_understood=True, primary_keys=('name', ), + versioned_fields=[ + ([('7.16', '>=')], 'matching-type', KeyInfo()), + ], fields={ 'address-pool': KeyInfo(default='none'), 'code': KeyInfo(required=True), From 22ff08978792c0d6798a301c9597f72a58afbb89 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 10 Oct 2024 21:43:40 +0200 Subject: [PATCH 275/365] Add cpu-frequency, memory-frequency, preboot-etherboot* properties (#320) Signed-off-by: Michael Hanselmann --- changelogs/fragments/320-add-routerboard-properties.yml | 2 ++ plugins/module_utils/_api_data.py | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 changelogs/fragments/320-add-routerboard-properties.yml diff --git a/changelogs/fragments/320-add-routerboard-properties.yml b/changelogs/fragments/320-add-routerboard-properties.yml new file mode 100644 index 0000000..c498dab --- /dev/null +++ b/changelogs/fragments/320-add-routerboard-properties.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``cpu-frequency``, ``memory-frequency``, ``preboot-etherboot`` and ``preboot-etherboot-server`` properties in ``system routerboard settings`` (https://github.com/ansible-collections/community.routeros/pull/320). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ae47274..6ecfeee 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4257,9 +4257,13 @@ PATHS = { 'boot-delay': KeyInfo(default='2s'), 'boot-device': KeyInfo(default='nand-if-fail-then-ethernet'), 'boot-protocol': KeyInfo(default='bootp'), + 'cpu-frequency': KeyInfo(), 'enable-jumper-reset': KeyInfo(default=True), 'enter-setup-on': KeyInfo(default='any-key'), 'force-backup-booter': KeyInfo(default=False), + 'memory-frequency': KeyInfo(), + 'preboot-etherboot': KeyInfo(), + 'preboot-etherboot-server': KeyInfo(), 'protected-routerboot': KeyInfo(default='disabled'), 'reformat-hold-button': KeyInfo(default='20s'), 'reformat-hold-button-max': KeyInfo(default='10m'), From 945e4d4d45aa55b4a90120167e0d371c40c1eaac Mon Sep 17 00:00:00 2001 From: liquorice-head <40302350+liquorice-head@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:36:36 +0400 Subject: [PATCH 276/365] add l2tp client interface configuration support (#322) * Update api_modify.py * Update api_info.py * Update _api_data.py * Create 322-add-l2tp-client-interface-configuration.yml * Update api_info.py * Update api_modify.py * Update _api_data.py * Update changelogs/fragments/322-add-l2tp-client-interface-configuration.yml Co-authored-by: Felix Fontein * Update _api_data.py --------- Co-authored-by: Felix Fontein --- ...dd-l2tp-client-interface-configuration.yml | 2 ++ plugins/module_utils/_api_data.py | 32 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 36 insertions(+) create mode 100644 changelogs/fragments/322-add-l2tp-client-interface-configuration.yml diff --git a/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml b/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml new file mode 100644 index 0000000..0278458 --- /dev/null +++ b/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support ``interface l2tp-client`` configuration (https://github.com/ansible-collections/community.routeros/pull/322). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 6ecfeee..a7985cf 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1519,6 +1519,38 @@ PATHS = { }, ), ), + ('interface', 'l2tp-client',): APIData( + unversioned=VersionedAPIData( + primary_keys=('name', ), + single_value=False, + fully_understood=True, + fields={ + 'add-default-route': KeyInfo(default=False), + 'allow': KeyInfo(default='pap,chap,mschap1,mschap2'), + 'allow-fast-path': KeyInfo(default=False), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connect-to': KeyInfo(required=True), + 'default-route-distance': KeyInfo(default=False), + 'dial-on-demand': KeyInfo(default=False), + 'disabled': KeyInfo(default=True), + 'ipsec-secret': KeyInfo(default=''), + 'keepalive-timeout': KeyInfo(default=60), + 'l2tp-proto-version': KeyInfo(default='l2tpv2'), + 'l2tpv3-cookie-length': KeyInfo(default=0), + 'l2tpv3-digest-hash': KeyInfo(default='md5'), + 'max-mru': KeyInfo(default=1450), + 'max-mtu': KeyInfo(default=1450), + 'mrru': KeyInfo(default='disabled'), + 'name': KeyInfo(required=True), + 'password': KeyInfo(), + 'profile': KeyInfo(default='default-encryption'), + 'src-address': KeyInfo(), + 'use-ipsec': KeyInfo(default=False), + 'use-peer-dns': KeyInfo(default=False), + 'user': KeyInfo(required=True), + }, + ), + ), ('interface', 'l2tp-server', 'server'): APIData( unversioned=VersionedAPIData( single_value=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index a1d979f..829fc17 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -69,6 +69,7 @@ options: - interface ethernet switch port - interface gre - interface gre6 + - interface l2tp-client - interface l2tp-server server - interface list - interface list member diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 24732a1..4975dc4 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -78,6 +78,7 @@ options: - interface ethernet switch port - interface gre - interface gre6 + - interface l2tp-client - interface l2tp-server server - interface list - interface list member From b499d9d7d90afd5bdd398250429f9915a8b7411c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Mon, 14 Oct 2024 20:50:36 +0200 Subject: [PATCH 277/365] Add new parameters from RouterOS 7.16 release (#323) * Add new parameters from RouterOS 7.16 release h3. /interface/bridge - `forward-reserved-addresses` with default value `False` - `max-learned-entries` with default value `auto` h3. /ip/neighbor/discovery-settings - `lldp-mac-phy-config` with default value `False` (from Router OS 7.15 release) - `discover-interval` with default value `30s` - `lldp-vlan-info` with default value `False` h3. /ip/settings - `ipv4-multipath-hash-policy` with default value `l3` h3. /ipv6/settings - `multipath-hash-policy` with default value `l3` h3. /ip/dhcp-server/option - `comment` h3. /ip/dhcp-server/option/sets - `comment` h3. /ip/dhcp-server/matcher - `comment` h3. /tool/netwatch - `acccept-icmp-time-exceeded` with default value `False` - `ttl` with defaut value `255` h3. /ip/service - `max-sessions` with default value `20` Add changelog fragment * Update changelogs/fragments/323-add-ros-7.16-parameters.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- .../fragments/323-add-ros-7.16-parameters.yml | 2 ++ plugins/module_utils/_api_data.py | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 changelogs/fragments/323-add-ros-7.16-parameters.yml diff --git a/changelogs/fragments/323-add-ros-7.16-parameters.yml b/changelogs/fragments/323-add-ros-7.16-parameters.yml new file mode 100644 index 0000000..a88580d --- /dev/null +++ b/changelogs/fragments/323-add-ros-7.16-parameters.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add new parameters from the RouterOS 7.16 release (https://github.com/ansible-collections/community.routeros/pull/323). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index a7985cf..847f5b1 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -262,6 +262,8 @@ PATHS = { versioned_fields=[ ([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)), ([('7.0', '>=')], 'ingress-filtering', KeyInfo(default=True)), + ([('7.16', '>=')], 'forward-reserved-addresses', KeyInfo(default=False)), + ([('7.16', '>=')], 'max-learned-entries', KeyInfo(default='auto')), ], fields={ 'admin-mac': KeyInfo(default=''), @@ -1450,6 +1452,9 @@ PATHS = { fully_understood=True, versioned_fields=[ ([('7.7', '>=')], 'mode', KeyInfo(default='tx-and-rx')), + ([('7.15', '>=')], 'lldp-mac-phy-config', KeyInfo(default=False)), + ([('7.16', '>=')], 'discover-interval', KeyInfo(default='30s')), + ([('7.16', '>=')], 'lldp-vlan-info', KeyInfo(default=False)), ], fields={ 'discover-interface-list': KeyInfo(), @@ -1462,6 +1467,9 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.16', '>=')], 'ipv4-multipath-hash-policy', KeyInfo(default='l3')), + ], fields={ 'accept-redirects': KeyInfo(default=False), 'accept-source-route': KeyInfo(default=False), @@ -1498,6 +1506,9 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.16', '>=')], 'multipath-hash-policy', KeyInfo(default='l3')), + ], fields={ 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), @@ -2807,6 +2818,9 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, primary_keys=('name',), + versioned_fields=[ + ([('7.16', '>=')], 'comment', KeyInfo(can_disable=True, remove_value='')), + ], fields={ 'code': KeyInfo(required=True), 'name': KeyInfo(), @@ -2819,6 +2833,9 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, primary_keys=('name',), + versioned_fields=[ + ([('7.16', '>=')], 'comment', KeyInfo(can_disable=True, remove_value='')), + ], fields={ 'name': KeyInfo(required=True), 'options': KeyInfo(), @@ -2831,6 +2848,7 @@ PATHS = { fully_understood=True, primary_keys=('name', ), versioned_fields=[ + ([('7.16', '>=')], 'comment', KeyInfo(can_disable=True, remove_value='')), ([('7.16', '>=')], 'matching-type', KeyInfo()), ], fields={ @@ -4458,6 +4476,10 @@ PATHS = { versioned=[ ('7', '>=', VersionedAPIData( fully_understood=True, + versioned_fields=[ + ([('7.16', '>=')], 'accept-icmp-time-exceeded', KeyInfo(default=False)), + ([('7.16', '>=')], 'ttl', KeyInfo(default=255)), + ], fields={ 'certificate': KeyInfo(), 'check-certificate': KeyInfo(), @@ -5133,6 +5155,9 @@ PATHS = { fixed_entries=True, primary_keys=('name', ), fully_understood=True, + versioned_fields=[ + ([('7.16', '>=')], 'max-sessions', KeyInfo(default=20)), + ], fields={ 'address': KeyInfo(), 'certificate': KeyInfo(), From c5e913fc13f22338fedc2e3ae424aa92ae2c7481 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 14 Oct 2024 20:59:23 +0200 Subject: [PATCH 278/365] Prepare 2.20.0 release. --- changelogs/fragments/2.20.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/2.20.0.yml diff --git a/changelogs/fragments/2.20.0.yml b/changelogs/fragments/2.20.0.yml new file mode 100644 index 0000000..63e0654 --- /dev/null +++ b/changelogs/fragments/2.20.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 2c9fe9a..3e1f73a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.19.0 +version: 2.12.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 031490c974d9742c3bde97cdff3362c6e668a133 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 17 Oct 2024 21:09:42 +0200 Subject: [PATCH 279/365] Fix typo. --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index 3e1f73a..7c40eda 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.12.0 +version: 2.20.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 26e3aa3e0a54cc8d01442841d8f89ec5b58d6754 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 17 Oct 2024 21:10:19 +0200 Subject: [PATCH 280/365] Release 2.20.0. --- CHANGELOG.md | 219 ++++++++++-------- CHANGELOG.rst | 16 ++ changelogs/changelog.yaml | 20 ++ changelogs/fragments/2.20.0.yml | 1 - .../320-add-routerboard-properties.yml | 2 - .../321-dhcp-server-matcher-matching-type.yml | 2 - ...dd-l2tp-client-interface-configuration.yml | 2 - .../fragments/323-add-ros-7.16-parameters.yml | 2 - 8 files changed, 155 insertions(+), 109 deletions(-) delete mode 100644 changelogs/fragments/2.20.0.yml delete mode 100644 changelogs/fragments/320-add-routerboard-properties.yml delete mode 100644 changelogs/fragments/321-dhcp-server-matcher-matching-type.yml delete mode 100644 changelogs/fragments/322-add-l2tp-client-interface-configuration.yml delete mode 100644 changelogs/fragments/323-add-ros-7.16-parameters.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c36e6..d104e3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,123 +2,126 @@ **Topics** -- v2\.19\.0 +- v2\.20\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v2\.19\.0 + +## v2\.20\.0 ### Release Summary @@ -128,6 +131,22 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. +* api\_info\, api\_modify \- add support interface l2tp\-client configuration \([https\://github\.com/ansible\-collections/community\.routeros/pull/322](https\://github\.com/ansible\-collections/community\.routeros/pull/322)\)\. +* api\_info\, api\_modify \- add support for the cpu\-frequency\, memory\-frequency\, preboot\-etherboot and preboot\-etherboot\-server properties in system routerboard settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/320](https\://github\.com/ansible\-collections/community\.routeros/pull/320)\)\. +* api\_info\, api\_modify \- add support for the matching\-type property in ip dhcp\-server matcher introduced by RouterOS 7\.16 \([https\://github\.com/ansible\-collections/community\.routeros/pull/321](https\://github\.com/ansible\-collections/community\.routeros/pull/321)\)\. + + +## v2\.19\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. * api\_info\, api\_modify \- add support for the mld\-version and multicast\-querier properties in interface bridge \([https\://github\.com/ansible\-collections/community\.routeros/pull/315](https\://github\.com/ansible\-collections/community\.routeros/pull/315)\)\. * api\_info\, api\_modify \- add support for the routing filter num\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/313](https\://github\.com/ansible\-collections/community\.routeros/pull/313)\)\. @@ -137,12 +156,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -166,12 +185,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -181,12 +200,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -195,12 +214,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -217,12 +236,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -232,12 +251,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -251,12 +270,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -270,12 +289,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -290,12 +309,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -327,12 +346,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -346,7 +365,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -367,7 +386,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -380,7 +399,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -393,12 +412,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -418,12 +437,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -436,12 +455,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -456,12 +475,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -474,12 +493,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -518,7 +537,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -531,12 +550,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -551,7 +570,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -565,12 +584,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -589,12 +608,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -618,12 +637,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -659,12 +678,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -680,12 +699,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -694,7 +713,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -707,7 +726,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -720,7 +739,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -733,12 +752,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 21df114..108831a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,22 @@ Community RouterOS Release Notes .. contents:: Topics +v2.20.0 +======= + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add new parameters from the RouterOS 7.16 release (https://github.com/ansible-collections/community.routeros/pull/323). +- api_info, api_modify - add support ``interface l2tp-client`` configuration (https://github.com/ansible-collections/community.routeros/pull/322). +- api_info, api_modify - add support for the ``cpu-frequency``, ``memory-frequency``, ``preboot-etherboot`` and ``preboot-etherboot-server`` properties in ``system routerboard settings`` (https://github.com/ansible-collections/community.routeros/pull/320). +- api_info, api_modify - add support for the ``matching-type`` property in ``ip dhcp-server matcher`` introduced by RouterOS 7.16 (https://github.com/ansible-collections/community.routeros/pull/321). + v2.19.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 3c64ad3..7185a2c 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -775,3 +775,23 @@ releases: - 313-add-routing-filter-num-list.yml - 315-bridge-mld-version-multicast-querier.yml release_date: '2024-09-10' + 2.20.0: + changes: + minor_changes: + - api_info, api_modify - add new parameters from the RouterOS 7.16 release + (https://github.com/ansible-collections/community.routeros/pull/323). + - api_info, api_modify - add support ``interface l2tp-client`` configuration + (https://github.com/ansible-collections/community.routeros/pull/322). + - api_info, api_modify - add support for the ``cpu-frequency``, ``memory-frequency``, + ``preboot-etherboot`` and ``preboot-etherboot-server`` properties in ``system + routerboard settings`` (https://github.com/ansible-collections/community.routeros/pull/320). + - api_info, api_modify - add support for the ``matching-type`` property in + ``ip dhcp-server matcher`` introduced by RouterOS 7.16 (https://github.com/ansible-collections/community.routeros/pull/321). + release_summary: Feature release. + fragments: + - 2.20.0.yml + - 320-add-routerboard-properties.yml + - 321-dhcp-server-matcher-matching-type.yml + - 322-add-l2tp-client-interface-configuration.yml + - 323-add-ros-7.16-parameters.yml + release_date: '2024-10-17' diff --git a/changelogs/fragments/2.20.0.yml b/changelogs/fragments/2.20.0.yml deleted file mode 100644 index 63e0654..0000000 --- a/changelogs/fragments/2.20.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. \ No newline at end of file diff --git a/changelogs/fragments/320-add-routerboard-properties.yml b/changelogs/fragments/320-add-routerboard-properties.yml deleted file mode 100644 index c498dab..0000000 --- a/changelogs/fragments/320-add-routerboard-properties.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``cpu-frequency``, ``memory-frequency``, ``preboot-etherboot`` and ``preboot-etherboot-server`` properties in ``system routerboard settings`` (https://github.com/ansible-collections/community.routeros/pull/320). diff --git a/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml b/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml deleted file mode 100644 index 78b8779..0000000 --- a/changelogs/fragments/321-dhcp-server-matcher-matching-type.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``matching-type`` property in ``ip dhcp-server matcher`` introduced by RouterOS 7.16 (https://github.com/ansible-collections/community.routeros/pull/321). diff --git a/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml b/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml deleted file mode 100644 index 0278458..0000000 --- a/changelogs/fragments/322-add-l2tp-client-interface-configuration.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support ``interface l2tp-client`` configuration (https://github.com/ansible-collections/community.routeros/pull/322). diff --git a/changelogs/fragments/323-add-ros-7.16-parameters.yml b/changelogs/fragments/323-add-ros-7.16-parameters.yml deleted file mode 100644 index a88580d..0000000 --- a/changelogs/fragments/323-add-ros-7.16-parameters.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add new parameters from the RouterOS 7.16 release (https://github.com/ansible-collections/community.routeros/pull/323). From e18de43407e0dc00d2e1678863f1748d7c2e0f8d Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 18 Oct 2024 21:01:46 +0200 Subject: [PATCH 281/365] Prepare 3.0.0 release (#318) * Prepare 3.0.0 release. * Install using ansible-galaxy via git instead of cloning directly. --- .github/workflows/ansible-test.yml | 67 ++---- .github/workflows/ee.yml | 5 - LICENSES/PSF-2.0.txt | 48 ---- README.md | 2 +- changelogs/fragments/3.0.0.yml | 7 + galaxy.yml | 2 +- meta/runtime.yml | 2 +- plugins/module_utils/_version.py | 345 ---------------------------- plugins/module_utils/version.py | 7 +- plugins/modules/command.py | 10 +- tests/sanity/extra/update-docs.json | 5 +- tests/sanity/extra/update-docs.py | 2 +- 12 files changed, 37 insertions(+), 465 deletions(-) delete mode 100644 LICENSES/PSF-2.0.txt create mode 100644 changelogs/fragments/3.0.0.yml delete mode 100644 plugins/module_utils/_version.py diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index ad01212..4431bea 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -26,12 +26,6 @@ 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 - - stable-2.10 - - stable-2.11 - - stable-2.12 - - stable-2.13 - - stable-2.14 - stable-2.15 - stable-2.16 - stable-2.17 @@ -54,10 +48,9 @@ jobs: ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: sanity - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - pre-test-cmd: |- - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + test-deps: >- + git+https://github.com/ansible-collections/ansible.utils.git,main + git+https://github.com/ansible-collections/ansible.netcommon.git,main units: # Ansible-test on various stable branches does not yet work well with cgroups v2. @@ -75,13 +68,6 @@ jobs: fail-fast: true matrix: ansible: - - stable-2.9 - - stable-2.10 - - stable-2.11 - - stable-2.12 - - stable-2.13 - - stable-2.14 - - stable-2.15 - stable-2.16 - stable-2.17 - stable-2.18 @@ -97,10 +83,9 @@ jobs: ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: units - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - pre-test-cmd: |- - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + test-deps: >- + git+https://github.com/ansible-collections/ansible.utils.git,main + git+https://github.com/ansible-collections/ansible.netcommon.git,main integration: # Ansible-test on various stable branches does not yet work well with cgroups v2. @@ -122,41 +107,24 @@ jobs: - "3.10" - "3.11" - "3.12" + - "3.13" include: - # 2.9 - - ansible: stable-2.9 - python: 2.7 - - ansible: stable-2.9 - python: 3.5 - # 2.10 - - ansible: stable-2.10 - python: 3.5 - # 2.11 - - ansible: stable-2.11 - python: 2.7 - - ansible: stable-2.11 - python: 3.6 - # 2.12 - - ansible: stable-2.12 - python: 3.8 - # 2.13 - - ansible: stable-2.13 - python: "3.10" - # 2.14 - - ansible: stable-2.14 - python: "3.11" # 2.15 - ansible: stable-2.15 - python: "3.9" + python: "2.7" + - ansible: stable-2.15 + python: "3.6" + - ansible: stable-2.15 + python: "3.7" # 2.16 - ansible: stable-2.16 python: "3.10" # 2.17 - ansible: stable-2.17 - python: "3.7" + python: "3.8" # 2.18 - ansible: stable-2.18 - python: "3.8" + python: "3.9" steps: - name: >- @@ -171,9 +139,8 @@ jobs: integration-continue-on-error: 'false' integration-diff: 'false' integration-retry-on-error: 'true' - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - pre-test-cmd: |- - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ../../ansible/netcommon - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ../../ansible/utils + test-deps: >- + git+https://github.com/ansible-collections/ansible.utils.git,main + git+https://github.com/ansible-collections/ansible.netcommon.git,main target-python-version: ${{ matrix.python }} testing-type: integration diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index cd6341f..9d6f3fd 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -57,11 +57,6 @@ jobs: ansible_runner: ansible-runner base_image: quay.io/rockylinux/rockylinux:9 pre_base: '"#"' - - name: ansible-core 2.14 @ CentOS Stream 9 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.14.tar.gz - ansible_runner: ansible-runner - base_image: quay.io/centos/centos:stream9 - pre_base: '"#"' runs-on: ubuntu-latest steps: - name: Check out code diff --git a/LICENSES/PSF-2.0.txt b/LICENSES/PSF-2.0.txt deleted file mode 100644 index 35acd7f..0000000 --- a/LICENSES/PSF-2.0.txt +++ /dev/null @@ -1,48 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. diff --git a/README.md b/README.md index a773b72..f7b488d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ For more information about communication, see the [Ansible communication guide]( ## Tested with Ansible -Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, and ansible-core 2.18 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. +Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, and ansible-core 2.18 releases and the current development version of ansible-core. Ansible 2.9, ansible-base 2.10, and ansible-core versions before 2.15.0 are not supported. ## External requirements diff --git a/changelogs/fragments/3.0.0.yml b/changelogs/fragments/3.0.0.yml new file mode 100644 index 0000000..4a71c2f --- /dev/null +++ b/changelogs/fragments/3.0.0.yml @@ -0,0 +1,7 @@ +release_summary: Major release that drops support for End of Life Python versions and fixes check mode for community.routeros.command. +removed_features: + - "The collection no longer supports Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14. + If you need to continue using End of Life versions of Ansible/ansible-base/ansible-core, please use community.routeros 2.x.y + (https://github.com/ansible-collections/community.routeros/pull/318)." +breaking_changes: + - "command - the module no longer declares that it supports check mode (https://github.com/ansible-collections/community.routeros/pull/318)." diff --git a/galaxy.yml b/galaxy.yml index 7c40eda..1508467 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 2.20.0 +version: 3.0.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) diff --git a/meta/runtime.yml b/meta/runtime.yml index 5aafd31..aae1259 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -3,7 +3,7 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -requires_ansible: '>=2.9.10' +requires_ansible: '>=2.15.0' action_groups: api: - api diff --git a/plugins/module_utils/_version.py b/plugins/module_utils/_version.py deleted file mode 100644 index f795407..0000000 --- a/plugins/module_utils/_version.py +++ /dev/null @@ -1,345 +0,0 @@ -# Vendored copy of distutils/version.py from CPython 3.9.5 -# -# Implements multiple version numbering conventions for the -# Python Module Distribution Utilities. -# -# Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. -# PSF License (see LICENSES/PSF-2.0.txt or https://opensource.org/licenses/Python-2.0) -# SPDX-License-Identifier: PSF-2.0 -# - -"""Provides classes to represent module version numbers (one class for -each style of version numbering). There are currently two such classes -implemented: StrictVersion and LooseVersion. - -Every version number class implements the following interface: - * the 'parse' method takes a string and parses it to some internal - representation; if the string is an invalid version number, - 'parse' raises a ValueError exception - * the class constructor takes an optional string argument which, - if supplied, is passed to 'parse' - * __str__ reconstructs the string that was passed to 'parse' (or - an equivalent string -- ie. one that will generate an equivalent - version number instance) - * __repr__ generates Python code to recreate the version number instance - * _cmp compares the current instance with either another instance - of the same class or a string (which will be parsed to an instance - of the same class, thus must follow the same rules) -""" - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import re - -try: - RE_FLAGS = re.VERBOSE | re.ASCII -except AttributeError: - RE_FLAGS = re.VERBOSE - - -class Version: - """Abstract base class for version numbering classes. Just provides - constructor (__init__) and reproducer (__repr__), because those - seem to be the same for all version numbering classes; and route - rich comparisons to _cmp. - """ - - def __init__(self, vstring=None): - if vstring: - self.parse(vstring) - - def __repr__(self): - return "%s ('%s')" % (self.__class__.__name__, str(self)) - - def __eq__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c == 0 - - def __lt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c < 0 - - def __le__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c <= 0 - - def __gt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c > 0 - - def __ge__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c >= 0 - - -# Interface for version-number classes -- must be implemented -# by the following classes (the concrete ones -- Version should -# be treated as an abstract class). -# __init__ (string) - create and take same action as 'parse' -# (string parameter is optional) -# parse (string) - convert a string representation to whatever -# internal representation is appropriate for -# this style of version numbering -# __str__ (self) - convert back to a string; should be very similar -# (if not identical to) the string supplied to parse -# __repr__ (self) - generate Python code to recreate -# the instance -# _cmp (self, other) - compare two version numbers ('other' may -# be an unparsed version string, or another -# instance of your version class) - - -class StrictVersion(Version): - """Version numbering for anal retentives and software idealists. - Implements the standard interface for version number classes as - described above. A version number consists of two or three - dot-separated numeric components, with an optional "pre-release" tag - on the end. The pre-release tag consists of the letter 'a' or 'b' - followed by a number. If the numeric components of two version - numbers are equal, then one with a pre-release tag will always - be deemed earlier (lesser) than one without. - - The following are valid version numbers (shown in the order that - would be obtained by sorting according to the supplied cmp function): - - 0.4 0.4.0 (these two are equivalent) - 0.4.1 - 0.5a1 - 0.5b3 - 0.5 - 0.9.6 - 1.0 - 1.0.4a3 - 1.0.4b1 - 1.0.4 - - The following are examples of invalid version numbers: - - 1 - 2.7.2.2 - 1.3.a4 - 1.3pl1 - 1.3c4 - - The rationale for this version numbering system will be explained - in the distutils documentation. - """ - - version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', - RE_FLAGS) - - def parse(self, vstring): - match = self.version_re.match(vstring) - if not match: - raise ValueError("invalid version number '%s'" % vstring) - - (major, minor, patch, prerelease, prerelease_num) = \ - match.group(1, 2, 4, 5, 6) - - if patch: - self.version = tuple(map(int, [major, minor, patch])) - else: - self.version = tuple(map(int, [major, minor])) + (0,) - - if prerelease: - self.prerelease = (prerelease[0], int(prerelease_num)) - else: - self.prerelease = None - - def __str__(self): - if self.version[2] == 0: - vstring = '.'.join(map(str, self.version[0:2])) - else: - vstring = '.'.join(map(str, self.version)) - - if self.prerelease: - vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) - - return vstring - - def _cmp(self, other): - if isinstance(other, str): - other = StrictVersion(other) - elif not isinstance(other, StrictVersion): - return NotImplemented - - if self.version != other.version: - # numeric versions don't match - # prerelease stuff doesn't matter - if self.version < other.version: - return -1 - else: - return 1 - - # have to compare prerelease - # case 1: neither has prerelease; they're equal - # case 2: self has prerelease, other doesn't; other is greater - # case 3: self doesn't have prerelease, other does: self is greater - # case 4: both have prerelease: must compare them! - - if (not self.prerelease and not other.prerelease): - return 0 - elif (self.prerelease and not other.prerelease): - return -1 - elif (not self.prerelease and other.prerelease): - return 1 - elif (self.prerelease and other.prerelease): - if self.prerelease == other.prerelease: - return 0 - elif self.prerelease < other.prerelease: - return -1 - else: - return 1 - else: - raise AssertionError("never get here") - -# end class StrictVersion - -# The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separated by a period or by -# sequences of letters. If only periods, then these are compared -# left-to-right to determine an ordering. -# 2) sequences of letters are part of the tuple for comparison and are -# compared lexicographically -# 3) recognize the numeric components may have leading zeroes -# -# The LooseVersion class below implements these rules: a version number -# string is split up into a tuple of integer and string components, and -# comparison is a simple tuple comparison. This means that version -# numbers behave in a predictable and obvious way, but a way that might -# not necessarily be how people *want* version numbers to behave. There -# wouldn't be a problem if people could stick to purely numeric version -# numbers: just split on period and compare the numbers as tuples. -# However, people insist on putting letters into their version numbers; -# the most common purpose seems to be: -# - indicating a "pre-release" version -# ('alpha', 'beta', 'a', 'b', 'pre', 'p') -# - indicating a post-release patch ('p', 'pl', 'patch') -# but of course this can't cover all version number schemes, and there's -# no way to know what a programmer means without asking him. -# -# The problem is what to do with letters (and other non-numeric -# characters) in a version number. The current implementation does the -# obvious and predictable thing: keep them as strings and compare -# lexically within a tuple comparison. This has the desired effect if -# an appended letter sequence implies something "post-release": -# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". -# -# However, if letters in a version number imply a pre-release version, -# the "obvious" thing isn't correct. Eg. you would expect that -# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison -# implemented here, this just isn't so. -# -# Two possible solutions come to mind. The first is to tie the -# comparison algorithm to a particular set of semantic rules, as has -# been done in the StrictVersion class above. This works great as long -# as everyone can go along with bondage and discipline. Hopefully a -# (large) subset of Python module programmers will agree that the -# particular flavour of bondage and discipline provided by StrictVersion -# provides enough benefit to be worth using, and will submit their -# version numbering scheme to its domination. The free-thinking -# anarchists in the lot will never give in, though, and something needs -# to be done to accommodate them. -# -# Perhaps a "moderately strict" version class could be implemented that -# lets almost anything slide (syntactically), and makes some heuristic -# assumptions about non-digits in version number strings. This could -# sink into special-case-hell, though; if I was as talented and -# idiosyncratic as Larry Wall, I'd go ahead and implement a class that -# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is -# just as happy dealing with things like "2g6" and "1.13++". I don't -# think I'm smart enough to do it right though. -# -# In any case, I've coded the test suite for this module (see -# ../test/test_version.py) specifically to fail on things like comparing -# "1.2a2" and "1.2". That's not because the *code* is doing anything -# wrong, it's because the simple, obvious design doesn't match my -# complicated, hairy expectations for real-world version numbers. It -# would be a snap to fix the test suite to say, "Yep, LooseVersion does -# the Right Thing" (ie. the code matches the conception). But I'd rather -# have a conception that matches common notions about version numbers. - - -class LooseVersion(Version): - """Version numbering for anarchists and software realists. - Implements the standard interface for version number classes as - described above. A version number consists of a series of numbers, - separated by either periods or strings of letters. When comparing - version numbers, the numeric components will be compared - numerically, and the alphabetic components lexically. The following - are all valid version numbers, in no particular order: - - 1.5.1 - 1.5.2b2 - 161 - 3.10a - 8.02 - 3.4j - 1996.07.12 - 3.2.pl0 - 3.1.1.6 - 2g6 - 11g - 0.960923 - 2.2beta29 - 1.13++ - 5.5.kw - 2.0b1pl0 - - In fact, there is no such thing as an invalid version number under - this scheme; the rules for comparison are simple and predictable, - but may not always give the results you want (for some definition - of "want"). - """ - - component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) - - def __init__(self, vstring=None): - if vstring: - self.parse(vstring) - - def parse(self, vstring): - # I've given up on thinking I can reconstruct the version string - # from the parsed tuple -- so I just store the string here for - # use by __str__ - self.vstring = vstring - components = [x for x in self.component_re.split(vstring) if x and x != '.'] - for i, obj in enumerate(components): - try: - components[i] = int(obj) - except ValueError: - pass - - self.version = components - - def __str__(self): - return self.vstring - - def __repr__(self): - return "LooseVersion ('%s')" % str(self) - - def _cmp(self, other): - if isinstance(other, str): - other = LooseVersion(other) - elif not isinstance(other, LooseVersion): - return NotImplemented - - if self.version == other.version: - return 0 - if self.version < other.version: - return -1 - if self.version > other.version: - return 1 - -# end class LooseVersion diff --git a/plugins/module_utils/version.py b/plugins/module_utils/version.py index dc01ffe..cc3028c 100644 --- a/plugins/module_utils/version.py +++ b/plugins/module_utils/version.py @@ -10,9 +10,4 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can -# remove the _version.py file, and replace the following import by -# -# from ansible.module_utils.compat.version import LooseVersion - -from ._version import LooseVersion # noqa: F401, pylint: disable=unused-import +from ansible.module_utils.compat.version import LooseVersion # pylint: disable=unused-import diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 52b916b..bf74d47 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -20,16 +20,14 @@ description: - The module always indicates a (changed) status. You can use R(the changed_when task property,override_the_changed_result) to determine whether a command task actually resulted in a change or not. -notes: - - The module declares that it B(supports check mode). This is a bug and will - be changed in community.routeros 3.0.0. extends_documentation_fragment: - community.routeros.attributes attributes: check_mode: - support: partial + support: none details: - - The module claims to support check mode, but it simply always executes the command. + - Before community.routeros 3.0.0, the module claimed to support check mode. + It simply executed the command in check mode. diff_mode: support: none platform: @@ -165,7 +163,7 @@ def main(): argument_spec.update(routeros_argument_spec) module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) + supports_check_mode=False) result = {'changed': False} diff --git a/tests/sanity/extra/update-docs.json b/tests/sanity/extra/update-docs.json index 029699f..3a63af8 100644 --- a/tests/sanity/extra/update-docs.json +++ b/tests/sanity/extra/update-docs.json @@ -4,5 +4,8 @@ "docs/docsite/rst/api-guide.rst", "plugins/modules/" ], - "output": "path-line-column-message" + "output": "path-line-column-message", + "requirements": [ + "ansible-core" + ] } diff --git a/tests/sanity/extra/update-docs.py b/tests/sanity/extra/update-docs.py index 68e2edf..6015512 100644 --- a/tests/sanity/extra/update-docs.py +++ b/tests/sanity/extra/update-docs.py @@ -12,7 +12,7 @@ import subprocess def main(): """Main entry point.""" - p = subprocess.run(['./update-docs.py'], check=False) + p = subprocess.run([sys.executable, 'update-docs.py'], check=False) if p.returncode not in (0, 1): print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) From 5fdbd52303a419b4033b26cebc6f8cfdcd50c763 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 19 Oct 2024 12:34:51 +0200 Subject: [PATCH 282/365] Fix reuse workflow branches. --- .github/workflows/reuse.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 7c15c11..b552396 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -7,9 +7,13 @@ name: Verify REUSE on: push: - branches: [main] + branches: + - main + - stable-* pull_request: - branches: [main] + branches: + - main + - stable-* # Run CI once per day (at 05:15 UTC) schedule: - cron: '15 5 * * *' From 5936c1ecefca748859d74c9ac3df0d2d03ef45e0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 20 Oct 2024 10:38:22 +0200 Subject: [PATCH 283/365] Release 3.0.0. --- CHANGELOG.md | 154 +++++++++++++++++++-------------- CHANGELOG.rst | 18 ++++ changelogs/changelog.yaml | 14 +++ changelogs/fragments/3.0.0.yml | 7 -- 4 files changed, 120 insertions(+), 73 deletions(-) delete mode 100644 changelogs/fragments/3.0.0.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d104e3f..55853f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,128 +2,150 @@ **Topics** -- v2\.20\.0 +- v3\.0\.0 - Release Summary + - Breaking Changes / Porting Guide + - Removed Features \(previously deprecated\) +- v2\.20\.0 + - Release Summary - Minor Changes - v2\.19\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.18\.0 - - Release Summary + - Release Summary - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.16\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.15\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.14\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.13\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.12\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.11\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.10\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.9\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.7\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.6\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.5\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.4\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary + - Release Summary - Minor Changes - - Breaking Changes / Porting Guide + - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary + - Release Summary - Minor Changes - Bugfixes - v1\.1\.0 - - Release Summary + - Release Summary - Minor Changes - v1\.0\.1 - - Release Summary + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary + - Release Summary - Minor Changes + +## v3\.0\.0 + + +### Release Summary + +Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. + + +### Breaking Changes / Porting Guide + +* command \- the module no longer declares that it supports check mode \([https\://github\.com/ansible\-collections/community\.routeros/pull/318](https\://github\.com/ansible\-collections/community\.routeros/pull/318)\)\. + + +### Removed Features \(previously deprecated\) + +* The collection no longer supports Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. If you need to continue using End of Life versions of Ansible/ansible\-base/ansible\-core\, please use community\.routeros 2\.x\.y \([https\://github\.com/ansible\-collections/community\.routeros/pull/318](https\://github\.com/ansible\-collections/community\.routeros/pull/318)\)\. + ## v2\.20\.0 - + ### Release Summary Feature release\. @@ -139,7 +161,7 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. @@ -156,7 +178,7 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. @@ -185,7 +207,7 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. @@ -200,7 +222,7 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. @@ -214,7 +236,7 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. @@ -236,7 +258,7 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. @@ -251,7 +273,7 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. @@ -270,7 +292,7 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. @@ -289,7 +311,7 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. @@ -309,7 +331,7 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. @@ -346,7 +368,7 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. @@ -365,7 +387,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -386,7 +408,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -399,7 +421,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -412,7 +434,7 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. @@ -437,7 +459,7 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. @@ -455,7 +477,7 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. @@ -475,7 +497,7 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. @@ -493,7 +515,7 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. @@ -537,7 +559,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -550,7 +572,7 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. @@ -570,7 +592,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -584,7 +606,7 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. @@ -608,7 +630,7 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. @@ -637,7 +659,7 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. @@ -649,7 +671,7 @@ A new major release with breaking changes in the behavior of community\.ro * command \- the commands and wait\_for options now convert the list elements to strings \([https\://github\.com/ansible\-collections/community\.routeros/pull/55](https\://github\.com/ansible\-collections/community\.routeros/pull/55)\)\. * facts \- the gather\_subset option now converts the list elements to strings \([https\://github\.com/ansible\-collections/community\.routeros/pull/55](https\://github\.com/ansible\-collections/community\.routeros/pull/55)\)\. - + ### Breaking Changes / Porting Guide * api \- due to a programming error\, the module never failed on errors\. This has now been fixed\. If you are relying on the module not failing in case of idempotent commands \(resulting in errors like failure\: already have such address\)\, you need to adjust your roles/playbooks\. We suggest to use failed\_when to accept failure in specific circumstances\, for example failed\_when\: \"\'failure\: already have \' in result\.msg\[0\]\" \([https\://github\.com/ansible\-collections/community\.routeros/pull/39](https\://github\.com/ansible\-collections/community\.routeros/pull/39)\)\. @@ -678,7 +700,7 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. @@ -699,7 +721,7 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. @@ -713,7 +735,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -726,7 +748,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -739,7 +761,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -752,7 +774,7 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 108831a..4b511c3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,24 @@ Community RouterOS Release Notes .. contents:: Topics +v3.0.0 +====== + +Release Summary +--------------- + +Major release that drops support for End of Life Python versions and fixes check mode for community.routeros.command. + +Breaking Changes / Porting Guide +-------------------------------- + +- command - the module no longer declares that it supports check mode (https://github.com/ansible-collections/community.routeros/pull/318). + +Removed Features (previously deprecated) +---------------------------------------- + +- The collection no longer supports Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14. If you need to continue using End of Life versions of Ansible/ansible-base/ansible-core, please use community.routeros 2.x.y (https://github.com/ansible-collections/community.routeros/pull/318). + v2.20.0 ======= diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 7185a2c..09b5b6d 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -795,3 +795,17 @@ releases: - 322-add-l2tp-client-interface-configuration.yml - 323-add-ros-7.16-parameters.yml release_date: '2024-10-17' + 3.0.0: + changes: + breaking_changes: + - command - the module no longer declares that it supports check mode (https://github.com/ansible-collections/community.routeros/pull/318). + release_summary: Major release that drops support for End of Life Python versions + and fixes check mode for community.routeros.command. + removed_features: + - The collection no longer supports Ansible 2.9, ansible-base 2.10, ansible-core + 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14. If you + need to continue using End of Life versions of Ansible/ansible-base/ansible-core, + please use community.routeros 2.x.y (https://github.com/ansible-collections/community.routeros/pull/318). + fragments: + - 3.0.0.yml + release_date: '2024-10-20' diff --git a/changelogs/fragments/3.0.0.yml b/changelogs/fragments/3.0.0.yml deleted file mode 100644 index 4a71c2f..0000000 --- a/changelogs/fragments/3.0.0.yml +++ /dev/null @@ -1,7 +0,0 @@ -release_summary: Major release that drops support for End of Life Python versions and fixes check mode for community.routeros.command. -removed_features: - - "The collection no longer supports Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, and ansible-core 2.14. - If you need to continue using End of Life versions of Ansible/ansible-base/ansible-core, please use community.routeros 2.x.y - (https://github.com/ansible-collections/community.routeros/pull/318)." -breaking_changes: - - "command - the module no longer declares that it supports check mode (https://github.com/ansible-collections/community.routeros/pull/318)." From d44262d820f9966f3f3e4608b6f6a07f403c5cf2 Mon Sep 17 00:00:00 2001 From: gardar Date: Mon, 4 Nov 2024 18:05:52 +0000 Subject: [PATCH 284/365] fix: add missing fields to `ip pool` path (#327) * fix: add missing fields to `ip pool` path Signed-off-by: gardar * fix: remove unneeded copy-from Signed-off-by: gardar --------- Signed-off-by: gardar --- changelogs/fragments/327-add-missing-ip-pool-fields.yml | 3 +++ plugins/module_utils/_api_data.py | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/327-add-missing-ip-pool-fields.yml diff --git a/changelogs/fragments/327-add-missing-ip-pool-fields.yml b/changelogs/fragments/327-add-missing-ip-pool-fields.yml new file mode 100644 index 0000000..54ee54d --- /dev/null +++ b/changelogs/fragments/327-add-missing-ip-pool-fields.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - api_info, api_modify - add missing fields ``comment``, ``next-pool`` to ``ip pool`` path (https://github.com/ansible-collections/community.routeros/pull/327). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 847f5b1..929aa19 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -708,7 +708,9 @@ PATHS = { fully_understood=True, primary_keys=('name', ), fields={ + 'comment': KeyInfo(), 'name': KeyInfo(), + 'next-pool': KeyInfo(), 'ranges': KeyInfo(), }, ), From 14d89a3cfa8d064e6d3f019c33f36db1b9bd5f36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 06:41:47 +0100 Subject: [PATCH 285/365] Bump fsfe/reuse-action from 4 to 5 (#328) Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 4 to 5. - [Release notes](https://github.com/fsfe/reuse-action/releases) - [Commits](https://github.com/fsfe/reuse-action/compare/v4...v5) --- updated-dependencies: - dependency-name: fsfe/reuse-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/reuse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index b552396..f6d5215 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -28,4 +28,4 @@ jobs: - uses: actions/checkout@v4 - name: REUSE Compliance Check - uses: fsfe/reuse-action@v4 + uses: fsfe/reuse-action@v5 From 249b1a92e2c2cdc1cd8786d9972aa58290723067 Mon Sep 17 00:00:00 2001 From: liquorice-head <40302350+liquorice-head@users.noreply.github.com> Date: Sat, 23 Nov 2024 03:19:05 +0400 Subject: [PATCH 286/365] Update _api_data.py (#324) * Update _api_data.py * Create 324-fix-firewall-log-and-log-prefix.yaml * Update changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml Co-authored-by: Felix Fontein * Update test_api_info.py * fix tests --------- Co-authored-by: Felix Fontein Co-authored-by: alsmirnov --- .../324-fix-firewall-log-and-log-prefix.yaml | 2 ++ plugins/module_utils/_api_data.py | 16 ++++++++-------- .../plugins/modules/test_api_find_and_modify.py | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml diff --git a/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml b/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml new file mode 100644 index 0000000..3c56470 --- /dev/null +++ b/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml @@ -0,0 +1,2 @@ +bugfixes: + - api_info, api_modify - fields ``log`` and ``log-prefix`` in paths ``ip firewall filter``, ``ip firewall mangle``, ``ip firewall nat``, ``ip firewall raw`` now have the correct default values (https://github.com/ansible-collections/community.routeros/pull/324). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 929aa19..bf0d335 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2986,8 +2986,8 @@ PATHS = { 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(can_disable=True), - 'log-prefix': KeyInfo(can_disable=True), + 'log': KeyInfo(default=False), + 'log-prefix': KeyInfo(default=''), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -3057,8 +3057,8 @@ PATHS = { 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(can_disable=True), - 'log-prefix': KeyInfo(can_disable=True), + 'log': KeyInfo(default=False), + 'log-prefix': KeyInfo(default=''), 'new-connection-mark': KeyInfo(can_disable=True), 'new-dscp': KeyInfo(can_disable=True), 'new-mss': KeyInfo(can_disable=True), @@ -3137,8 +3137,8 @@ PATHS = { 'jump-target': KeyInfo(can_disable=True), 'layer7-protocol': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(can_disable=True), - 'log-prefix': KeyInfo(can_disable=True), + 'log': KeyInfo(default=False), + 'log-prefix': KeyInfo(default=''), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), @@ -3200,8 +3200,8 @@ PATHS = { 'ipv4-options': KeyInfo(can_disable=True), 'jump-target': KeyInfo(can_disable=True), 'limit': KeyInfo(can_disable=True), - 'log': KeyInfo(can_disable=True), - 'log-prefix': KeyInfo(can_disable=True), + 'log': KeyInfo(default=False), + 'log-prefix': KeyInfo(default=''), 'nth': KeyInfo(can_disable=True), 'out-bridge-port': KeyInfo(can_disable=True), 'out-bridge-port-list': KeyInfo(can_disable=True), diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index 2f47af4..e6eb00b 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -620,6 +620,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'defconf', 'protocol': 'icmp', 'disabled': False, + 'log': False, + 'log-prefix': '', }, { '.id': '*3', @@ -627,6 +629,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'input', 'comment': 'defconf', 'disabled': False, + 'log': False, + 'log-prefix': '', }, { '.id': '*4', @@ -634,6 +638,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'chain': 'input', 'comment': 'defconf', 'disabled': False, + 'log': False, + 'log-prefix': '', }, { '.id': '*7', @@ -642,6 +648,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'defconf', 'disabled': False, 'in-interface': 'wan', + 'log': False, + 'log-prefix': '', }, { '.id': '*8', @@ -650,6 +658,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'defconf', 'connection-state': 'established', 'disabled': False, + 'log': False, + 'log-prefix': '', }, { '.id': '*9', @@ -658,6 +668,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'defconf', 'connection-state': 'related', 'disabled': False, + 'log': False, + 'log-prefix': '', }, { '.id': '*A', @@ -666,6 +678,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'defconf', 'connection-status': 'invalid', 'disabled': False, + 'log': False, + 'log-prefix': '', }, ]) self.assertEqual(result['match_count'], 3) From c27c1906aa90295316b77d1f239ab4142e709571 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 2 Dec 2024 20:38:57 +0100 Subject: [PATCH 287/365] Re-classify change as feature. --- changelogs/fragments/327-add-missing-ip-pool-fields.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/327-add-missing-ip-pool-fields.yml b/changelogs/fragments/327-add-missing-ip-pool-fields.yml index 54ee54d..e7e05b7 100644 --- a/changelogs/fragments/327-add-missing-ip-pool-fields.yml +++ b/changelogs/fragments/327-add-missing-ip-pool-fields.yml @@ -1,3 +1,3 @@ --- -bugfixes: +minor_changes: - api_info, api_modify - add missing fields ``comment``, ``next-pool`` to ``ip pool`` path (https://github.com/ansible-collections/community.routeros/pull/327). From 8dbad9a8d4a82ca9331b8867fb2987fbf18840cd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 2 Dec 2024 20:39:15 +0100 Subject: [PATCH 288/365] Prepare 3.1.0. --- changelogs/fragments/3.1.0.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/fragments/3.1.0.yml diff --git a/changelogs/fragments/3.1.0.yml b/changelogs/fragments/3.1.0.yml new file mode 100644 index 0000000..56de6d9 --- /dev/null +++ b/changelogs/fragments/3.1.0.yml @@ -0,0 +1 @@ +release_summary: Bugfix and feature release. From c3e57efa9d9ef6c75f57c9bc8dda463b7f2fbdac Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 2 Dec 2024 20:44:15 +0100 Subject: [PATCH 289/365] Forgot to bump version. --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index 1508467..e59c543 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.0.0 +version: 3.1.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 0bf4b3ef8cb570de634092da8323d4ebd40a7d7b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 2 Dec 2024 20:45:03 +0100 Subject: [PATCH 290/365] Release 3.1.0. --- CHANGELOG.md | 352 ++++++++++-------- CHANGELOG.rst | 18 + changelogs/changelog.yaml | 15 + changelogs/fragments/3.1.0.yml | 1 - .../324-fix-firewall-log-and-log-prefix.yaml | 2 - .../327-add-missing-ip-pool-fields.yml | 3 - 6 files changed, 220 insertions(+), 171 deletions(-) delete mode 100644 changelogs/fragments/3.1.0.yml delete mode 100644 changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml delete mode 100644 changelogs/fragments/327-add-missing-ip-pool-fields.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 55853f0..135eb61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,132 +2,154 @@ **Topics** -- v3\.0\.0 +- v3\.1\.0 - Release Summary + - Minor Changes + - Bugfixes +- v3\.0\.0 + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes - - Deprecated Features - - Bugfixes -- v2\.17\.0 +- v2\.18\.0 - Release Summary - Minor Changes -- v2\.16\.0 + - Deprecated Features + - Bugfixes +- v2\.17\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - Minor Changes - Bugfixes - - Known Issues -- v2\.3\.1 +- v2\.4\.0 - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - Minor Changes - Bugfixes -- v2\.2\.1 + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary - Bugfixes - - New Modules -- v2\.1\.0 +- v2\.2\.0 - Release Summary - Minor Changes - Bugfixes - - New Modules -- v2\.0\.0 + - New Modules +- v2\.1\.0 - Release Summary - Minor Changes - - Breaking Changes / Porting Guide - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 - - Release Summary - Bugfixes -- v1\.0\.0 +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary - - Minor Changes + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes + + +## v3\.1\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. + + +### Bugfixes + +* api\_info\, api\_modify \- fields log and log\-prefix in paths ip firewall filter\, ip firewall mangle\, ip firewall nat\, ip firewall raw now have the correct default values \([https\://github\.com/ansible\-collections/community\.routeros/pull/324](https\://github\.com/ansible\-collections/community\.routeros/pull/324)\)\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -145,12 +167,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -161,12 +183,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -178,12 +200,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -199,7 +221,7 @@ Feature release\. * The collection deprecates support for all Ansible/ansible\-base/ansible\-core versions that are currently End of Life\, [according to the ansible\-core support matrix](https\://docs\.ansible\.com/ansible\-core/devel/reference\_appendices/release\_and\_maintenance\.html\#ansible\-core\-support\-matrix)\. This means that the next major release of the collection will no longer support Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. - + ### Bugfixes * api\_modify\, api\_info \- change the default of ingress\-filtering in paths interface bridge and interface bridge port back to false for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -207,21 +229,6 @@ Feature release\. ## v2\.17\.0 - -### Release Summary - -Feature release\. - - -### Minor Changes - -* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. -* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. -* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - - -## v2\.16\.0 - ### Release Summary @@ -230,11 +237,12 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. -* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. +* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. +* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. +* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -244,6 +252,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -258,12 +280,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -273,18 +295,18 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + ### Bugfixes * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. @@ -292,12 +314,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -311,12 +333,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -331,12 +353,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -360,7 +382,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -368,18 +390,18 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -387,7 +409,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -408,19 +430,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -429,35 +438,23 @@ Bugfix release\. ### Bugfixes -* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - -## v2\.8\.0 + +## v2\.8\.1 ### Release Summary -Bugfix and feature release\. - - -### Minor Changes - -* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. -* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. -* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. -* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. +Bugfix release\. ### Bugfixes -* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. - -## v2\.7\.0 + +## v2\.8\.0 ### Release Summary @@ -467,28 +464,53 @@ Bugfix and feature release\. ### Minor Changes -* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. ### Bugfixes +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -497,17 +519,17 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -515,12 +537,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -541,7 +563,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -559,7 +581,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -572,19 +594,19 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -592,12 +614,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -606,17 +628,17 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -630,12 +652,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -644,7 +666,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -659,12 +681,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -678,7 +700,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -700,12 +722,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -713,7 +735,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -721,12 +743,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -735,12 +757,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -748,12 +770,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -761,12 +783,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -774,12 +796,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4b511c3..fdfeca0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,24 @@ Community RouterOS Release Notes .. contents:: Topics +v3.1.0 +====== + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_info, api_modify - add missing fields ``comment``, ``next-pool`` to ``ip pool`` path (https://github.com/ansible-collections/community.routeros/pull/327). + +Bugfixes +-------- + +- api_info, api_modify - fields ``log`` and ``log-prefix`` in paths ``ip firewall filter``, ``ip firewall mangle``, ``ip firewall nat``, ``ip firewall raw`` now have the correct default values (https://github.com/ansible-collections/community.routeros/pull/324). + v3.0.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 09b5b6d..8522a87 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -809,3 +809,18 @@ releases: fragments: - 3.0.0.yml release_date: '2024-10-20' + 3.1.0: + changes: + bugfixes: + - api_info, api_modify - fields ``log`` and ``log-prefix`` in paths ``ip firewall + filter``, ``ip firewall mangle``, ``ip firewall nat``, ``ip firewall raw`` + now have the correct default values (https://github.com/ansible-collections/community.routeros/pull/324). + minor_changes: + - api_info, api_modify - add missing fields ``comment``, ``next-pool`` to + ``ip pool`` path (https://github.com/ansible-collections/community.routeros/pull/327). + release_summary: Bugfix and feature release. + fragments: + - 3.1.0.yml + - 324-fix-firewall-log-and-log-prefix.yaml + - 327-add-missing-ip-pool-fields.yml + release_date: '2024-12-02' diff --git a/changelogs/fragments/3.1.0.yml b/changelogs/fragments/3.1.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/3.1.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. diff --git a/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml b/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml deleted file mode 100644 index 3c56470..0000000 --- a/changelogs/fragments/324-fix-firewall-log-and-log-prefix.yaml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - api_info, api_modify - fields ``log`` and ``log-prefix`` in paths ``ip firewall filter``, ``ip firewall mangle``, ``ip firewall nat``, ``ip firewall raw`` now have the correct default values (https://github.com/ansible-collections/community.routeros/pull/324). diff --git a/changelogs/fragments/327-add-missing-ip-pool-fields.yml b/changelogs/fragments/327-add-missing-ip-pool-fields.yml deleted file mode 100644 index e7e05b7..0000000 --- a/changelogs/fragments/327-add-missing-ip-pool-fields.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - api_info, api_modify - add missing fields ``comment``, ``next-pool`` to ``ip pool`` path (https://github.com/ansible-collections/community.routeros/pull/327). From a7340eae1a26ae269655c8ac0c75ec05e7760ae9 Mon Sep 17 00:00:00 2001 From: Serhiy Date: Sat, 14 Dec 2024 15:20:58 +0200 Subject: [PATCH 291/365] community-list for /routing/filter (#331) * Update _api_data.py added ('routing', 'filter', 'community-list') * Update api_info.py added routing filter community-list * Update api_modify.py added routing filter community-list * Create 331-add-routing-filter-community-list.yml * Update api_info.py * Update api_modify.py --- .../331-add-routing-filter-community-list.yml | 2 ++ plugins/module_utils/_api_data.py | 14 ++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 18 insertions(+) create mode 100644 changelogs/fragments/331-add-routing-filter-community-list.yml diff --git a/changelogs/fragments/331-add-routing-filter-community-list.yml b/changelogs/fragments/331-add-routing-filter-community-list.yml new file mode 100644 index 0000000..e4cb0ba --- /dev/null +++ b/changelogs/fragments/331-add-routing-filter-community-list.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``routing filter community-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/331). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index bf0d335..cb9ff98 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -895,6 +895,20 @@ PATHS = { )), ], ), + ('routing', 'filter', 'community-list'): APIData( + versioned=[ + ('7', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'list': KeyInfo(required=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(can_disable=True), + 'communities': KeyInfo(can_disable=True), + 'regexp': KeyInfo(can_disable=True), + }, + )), + ], + ), ('routing', 'ospf', 'instance'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 829fc17..5b34463 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -205,6 +205,7 @@ options: - routing bgp peer - routing bgp template - routing filter + - routing filter community-list - routing filter num-list - routing filter rule - routing filter select-rule diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 4975dc4..9ab34d9 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -214,6 +214,7 @@ options: - routing bgp peer - routing bgp template - routing filter + - routing filter community-list - routing filter num-list - routing filter rule - routing filter select-rule From 995ab18e7bf30886030394cbabeed07bde785333 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 14 Dec 2024 14:56:14 +0100 Subject: [PATCH 292/365] Fix some issues pointed out by zizmor. (#333) --- .github/workflows/ee.yml | 3 ++- .github/workflows/extra-tests.yml | 1 + .github/workflows/reuse.yml | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 9d6f3fd..b04d197 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -63,6 +63,7 @@ jobs: uses: actions/checkout@v4 with: path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} + persist-credentials: false - name: Set up Python uses: actions/setup-python@v5 @@ -96,7 +97,7 @@ jobs: - name: Create files for building execution environment run: | - COLLECTION_FILENAME="$(ls "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)" + COLLECTION_FILENAME="$(ls "${NAMESPACE}-${COLLECTION_NAME}"-*.tar.gz)" # EE config cat > execution-environment.yml < Date: Sat, 28 Dec 2024 14:27:15 +0100 Subject: [PATCH 293/365] Improve language. --- plugins/module_utils/_api_data.py | 2 +- plugins/module_utils/api.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index cb9ff98..25dd4cb 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -5158,7 +5158,7 @@ PATHS = { 'protocol': KeyInfo(default='all'), 'src-address': KeyInfo(), 'src-port': KeyInfo(default='any'), - # The template field can't really be changed once the item is + # The template field ca not really be changed once the item is # created. This config captures the behavior best as it can # i.e. template=yes is shown, template=no is hidden. 'template': KeyInfo(can_disable=True, remove_value=False), diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index 6c276d7..aa3aa2e 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -77,7 +77,7 @@ def _ros_api_connect(module, username, password, host, port, use_tls, force_no_c elif not validate_cert_hostname: ctx.check_hostname = False else: - # Since librouteros doesn't pass server_hostname, + # Since librouteros does not pass server_hostname, # we have to do this ourselves: def wrap_context(*args, **kwargs): kwargs.pop('server_hostname', None) From 539119c57da13a18f4968734dbf94fa0136bf672 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 28 Dec 2024 15:34:20 +0100 Subject: [PATCH 294/365] Reformat documentation with 'andebox yaml-doc' (#335) * Reformat documentation with 'andebox yaml-doc'. * Revert unwanted changes. --- plugins/cliconf/routeros.py | 9 +- plugins/doc_fragments/api.py | 39 +- plugins/doc_fragments/attributes.py | 62 +-- plugins/modules/api.py | 63 +-- plugins/modules/api_facts.py | 35 +- plugins/modules/api_find_and_modify.py | 111 +++-- plugins/modules/api_info.py | 493 +++++++++++----------- plugins/modules/api_modify.py | 557 ++++++++++++------------- plugins/modules/command.py | 71 ++-- plugins/modules/facts.py | 33 +- update-docs.py | 2 +- 11 files changed, 717 insertions(+), 758 deletions(-) diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py index 412627b..1c3288f 100644 --- a/plugins/cliconf/routeros.py +++ b/plugins/cliconf/routeros.py @@ -5,15 +5,14 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" author: "Egor Zaitsev (@heuels)" name: routeros short_description: Use routeros cliconf to run command on MikroTik RouterOS platform description: - - This routeros plugin provides low level abstraction apis for - sending and receiving CLI commands from MikroTik RouterOS network devices. -''' + - This routeros plugin provides low level abstraction apis for sending and receiving CLI commands from MikroTik RouterOS + network devices. +""" import re import json diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index b0ad979..edef5f0 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -10,7 +10,7 @@ __metaclass__ = type class ModuleDocFragment(object): - DOCUMENTATION = r''' + DOCUMENTATION = r""" options: hostname: description: @@ -50,10 +50,9 @@ options: description: - Set to V(true) to connect without a certificate when O(tls=true). - See also O(validate_certs). - - B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible - to Man-in-the-Middle attacks, because the keys used in the exchange are not authenticated. - Instead of simply connecting without a certificate to "make things work" have a look at - O(validate_certs) and O(ca_path). + - B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible to Man-in-the-Middle + attacks, because the keys used in the exchange are not authenticated. Instead of simply connecting without a certificate + to "make things work" have a look at O(validate_certs) and O(ca_path). type: bool default: false version_added: 2.4.0 @@ -61,10 +60,9 @@ options: description: - Set to V(false) to skip validation of TLS certificates. - See also O(validate_cert_hostname). Only used when O(tls=true). - - B(Note:) instead of simply deactivating certificate validations to "make things work", - please consider creating your own CA certificate and using it to sign certificates used - for your router. You can tell the module about your CA certificate with the O(ca_path) - option. + - B(Note:) instead of simply deactivating certificate validations to "make things work", please consider creating your + own CA certificate and using it to sign certificates used for your router. You can tell the module about your CA certificate + with the O(ca_path) option. type: bool default: true version_added: 1.2.0 @@ -93,10 +91,10 @@ requirements: - Python >= 3.6 (for librouteros) seealso: - ref: ansible_collections.community.routeros.docsite.api-guide - description: How to connect to RouterOS devices with the RouterOS API -''' + description: How to connect to RouterOS devices with the RouterOS API. +""" - RESTRICT = r''' + RESTRICT = r""" options: restrict: type: list @@ -115,24 +113,21 @@ options: values: description: - The values of the field to limit to. - - >- - Note that the types of the values are important. If you provide a string V("0"), - and librouteros converts the value returned by the API to the integer V(0), - then this will not match. If you are not sure, better include both variants: - both the string and the integer. + - 'Note that the types of the values are important. If you provide a string V("0"), and librouteros converts the + value returned by the API to the integer V(0), then this will not match. If you are not sure, better include both + variants: both the string and the integer.' type: list elements: raw regex: description: - A regular expression matching values of the field to limit to. - Note that all values will be converted to strings before matching. - - It is not possible to match disabled values with regular expressions. - Set O(restrict[].match_disabled=true) if you also want to match disabled values. + - It is not possible to match disabled values with regular expressions. Set O(restrict[].match_disabled=true) if + you also want to match disabled values. type: str invert: description: - - Invert the condition. This affects O(restrict[].match_disabled), O(restrict[].values), - and O(restrict[].regex). + - Invert the condition. This affects O(restrict[].match_disabled), O(restrict[].values), and O(restrict[].regex). type: bool default: false -''' +""" diff --git a/plugins/doc_fragments/attributes.py b/plugins/doc_fragments/attributes.py index e18a48f..8c5c145 100644 --- a/plugins/doc_fragments/attributes.py +++ b/plugins/doc_fragments/attributes.py @@ -11,17 +11,17 @@ __metaclass__ = type class ModuleDocFragment(object): # Standard documentation fragment - DOCUMENTATION = r''' + DOCUMENTATION = r""" options: {} attributes: - check_mode: - description: Can run in C(check_mode) and return changed status prediction without modifying target. - diff_mode: - description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode. - platform: - description: Target OS/families that can be operated against. - support: N/A -''' + check_mode: + description: Can run in C(check_mode) and return changed status prediction without modifying target. + diff_mode: + description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode. + platform: + description: Target OS/families that can be operated against. + support: N/A +""" # Should be used together with the standard fragment INFO_MODULE = r''' @@ -47,23 +47,23 @@ attributes: - community.routeros.api ''' - CONN = r''' + CONN = r""" options: {} attributes: - become: - description: Is usable alongside C(become) keywords. - connection: - description: Uses the target's configured connection information to execute code on it. - delegation: - description: Can be used in conjunction with C(delegate_to) and related keywords. -''' + become: + description: Is usable alongside C(become) keywords. + connection: + description: Uses the target's configured connection information to execute code on it. + delegation: + description: Can be used in conjunction with C(delegate_to) and related keywords. +""" - FACTS = r''' + FACTS = r""" options: {} attributes: - facts: - description: Action returns an C(ansible_facts) dictionary that will update existing host facts. -''' + facts: + description: Action returns an C(ansible_facts) dictionary that will update existing host facts. +""" # Should be used together with the standard fragment and the FACTS fragment FACTS_MODULE = r''' @@ -81,18 +81,18 @@ attributes: support: full ''' - FILES = r''' + FILES = r""" options: {} attributes: - safe_file_operations: - description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption. -''' + safe_file_operations: + description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption. +""" - FLOW = r''' + FLOW = r""" options: {} attributes: - action: - description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller. - async: - description: Supports being used with the C(async) keyword. -''' + action: + description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller. + async: + description: Supports being used with the C(async) keyword. +""" diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 4857a3c..ecd99e0 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -8,8 +8,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: api author: "Nikolay Dachev (@NikolayDachev)" short_description: Ansible module for RouterOS API @@ -18,9 +17,8 @@ description: - This module can add, remove, update, query and execute arbitrary command in RouterOS via API. notes: - O(add), O(remove), O(update), O(cmd), and O(query) are mutually exclusive. - - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules - for more specific modifications, and the M(community.routeros.api_info) module for a more controlled - way of returning all entries for a path. + - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules for more specific modifications, + and the M(community.routeros.api_info) module for a more controlled way of returning all entries for a path. extends_documentation_fragment: - community.routeros.api - community.routeros.attributes @@ -68,11 +66,12 @@ options: - Query given path for selected query attributes from RouterOS aip. - WHERE is key word which extend query. WHERE format is key operator value - with spaces. - WHERE valid operators are V(==) or V(eq), V(!=) or V(not), V(>) or V(more), V(<) or V(less). - - Example path V(ip address) and query V(.id address) will return only C(.id) and C(address) for all items in V(ip address) path. - - Example path V(ip address) and query V(.id address WHERE address == 1.1.1.3/32). - will return only C(.id) and C(address) for items in V(ip address) path, where address is eq to 1.1.1.3/32. - - Example path V(interface) and query V(mtu name WHERE mut > 1400) will - return only interfaces C(mtu,name) where mtu is bigger than 1400. + - Example path V(ip address) and query V(.id address) will return only C(.id) and C(address) for all items in V(ip address) + path. + - Example path V(ip address) and query V(.id address WHERE address == 1.1.1.3/32). will return only C(.id) and C(address) + for items in V(ip address) path, where address is eq to 1.1.1.3/32. + - Example path V(interface) and query V(mtu name WHERE mut > 1400) will return only interfaces C(mtu,name) where mtu + is bigger than 1400. - Equivalent in RouterOS CLI C(/interface print where mtu > 1400). type: str extended_query: @@ -91,7 +90,8 @@ options: where: description: - Allows to restrict the objects returned. - - The conditions here must all match. An O(extended_query.where[].or) condition needs at least one of its conditions to match. + - The conditions here must all match. An O(extended_query.where[].or) condition needs at least one of its conditions + to match. type: list elements: dict suboptions: @@ -105,7 +105,8 @@ options: description: - The operator to use for matching. - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more). - - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].value) must be a list. + - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].value) must + be a list. - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is), and O(extended_query.where[].value) have to be specified. type: str @@ -133,7 +134,8 @@ options: description: - The operator to use for matching. - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more). - - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].or[].value) must be a list. + - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].or[].value) + must be a list. type: str choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"] required: true @@ -150,14 +152,14 @@ options: type: str seealso: - ref: ansible_collections.community.routeros.docsite.quoting - description: How to quote and unquote commands and arguments + description: How to quote and unquote commands and arguments. - module: community.routeros.api_facts - module: community.routeros.api_find_and_modify - module: community.routeros.api_info - module: community.routeros.api_modify -''' +""" -EXAMPLES = ''' +EXAMPLES = r""" - name: Get example - ip address print community.routeros.api: hostname: "{{ hostname }}" @@ -216,8 +218,8 @@ EXAMPLES = ''' - attribute: "network" is: "in" value: - - "10.20.36.0" - - "192.168.255.0" + - "10.20.36.0" + - "192.168.255.0" register: extended_queryout - name: Dump "Extended query example" output @@ -231,9 +233,9 @@ EXAMPLES = ''' username: "{{ username }}" path: "ip address" update: >- - .id=*14 - address=192.168.255.20/24 - comment={{ 'Update 192.168.255.10/24 to 192.168.255.20/24 on ether2' | community.routeros.quote_argument_value }} + .id=*14 + address=192.168.255.20/24 + comment={{ 'Update 192.168.255.10/24 to 192.168.255.20/24 on ether2' | community.routeros.quote_argument_value }} - name: Remove example - ether2 ip 192.168.255.20/24 with ".id = *14" community.routeros.api: @@ -255,18 +257,17 @@ EXAMPLES = ''' - name: Dump "Arbitrary command example" output ansible.builtin.debug: msg: '{{ arbitraryout }}' -''' +""" -RETURN = ''' ---- +RETURN = r""" message: - description: All outputs are in list with dictionary elements returned from RouterOS api. - sample: - - address: 1.2.3.4 - - address: 2.3.4.5 - type: list - returned: always -''' + description: All outputs are in list with dictionary elements returned from RouterOS api. + sample: + - address: 1.2.3.4 + - address: 2.3.4.5 + type: list + returned: always +""" from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.text.converters import to_native diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 296621e..e1fb70a 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -9,23 +9,20 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: api_facts author: - - "Egor Zaitsev (@heuels)" - - "Nikolay Dachev (@NikolayDachev)" - - "Felix Fontein (@felixfontein)" + - "Egor Zaitsev (@heuels)" + - "Nikolay Dachev (@NikolayDachev)" + - "Felix Fontein (@felixfontein)" version_added: 2.1.0 short_description: Collect facts from remote devices running MikroTik RouterOS using the API description: - - Collects a base set of device facts from a remote device that - is running RouterOS. This module prepends all of the - base network fact keys with C(ansible_net_). The facts - module will always collect a base set of facts from the device + - Collects a base set of device facts from a remote device that is running RouterOS. This module prepends all of the base + network fact keys with C(ansible_net_). The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. - - As opposed to the M(community.routeros.facts) module, it uses the - RouterOS API, similar to the M(community.routeros.api) module. + - As opposed to the M(community.routeros.facts) module, it uses the RouterOS API, similar to the M(community.routeros.api) + module. extends_documentation_fragment: - community.routeros.api - community.routeros.attributes @@ -39,12 +36,10 @@ attributes: options: gather_subset: description: - - When supplied, this argument will restrict the facts collected - to a given subset. Possible values for this argument include - V(all), V(hardware), V(interfaces), and V(routing). - - Can specify a list of values to include a larger subset. - Values can also be used with an initial V(!) to specify that a - specific subset should not be collected. + - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument + include V(all), V(hardware), V(interfaces), and V(routing). + - Can specify a list of values to include a larger subset. Values can also be used with an initial V(!) to specify that + a specific subset should not be collected. required: false default: - all @@ -56,9 +51,9 @@ seealso: - module: community.routeros.api_find_and_modify - module: community.routeros.api_info - module: community.routeros.api_modify -''' +""" -EXAMPLES = """ +EXAMPLES = r""" - name: Collect all facts from the device community.routeros.api_facts: hostname: 192.168.88.1 @@ -75,7 +70,7 @@ EXAMPLES = """ - "!hardware" """ -RETURN = """ +RETURN = r""" ansible_facts: description: "Dictionary of IP geolocation facts for a host's IP address." returned: always diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 176c943..f6aab9f 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -8,8 +8,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: api_find_and_modify author: - "Felix Fontein (@felixfontein)" @@ -17,13 +16,13 @@ short_description: Find and modify information using the API version_added: 2.1.0 description: - Allows to find entries for a path by conditions and modify the values of these entries. - - Use the M(community.routeros.api_find_and_modify) module to set all entries of a path to specific values, - or change multiple entries in different ways in one step. + - Use the M(community.routeros.api_find_and_modify) module to set all entries of a path to specific values, or change multiple + entries in different ways in one step. notes: - - "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that - there are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true). - This will make the module fail if there are less than N such entries, but not if there is no match. The latter case - is needed for idempotency of the task: once the values have been changed, there should be no further match." + - "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that there + are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true). This will make + the module fail if there are less than N such entries, but not if there is no match. The latter case is needed for idempotency + of the task: once the values have been changed, there should be no further match." extends_documentation_fragment: - community.routeros.api - community.routeros.attributes @@ -79,10 +78,9 @@ seealso: - module: community.routeros.api_facts - module: community.routeros.api_modify - module: community.routeros.api_info -''' +""" -EXAMPLES = ''' ---- +EXAMPLES = r""" - name: Rename bridge from 'bridge' to 'my-bridge' community.routeros.api_find_and_modify: hostname: "{{ hostname }}" @@ -104,59 +102,58 @@ EXAMPLES = ''' interface: bridge values: address: "192.168.1.1/24" - # If there are zero entries, or more than one: fail! We expected that - # exactly one is configured. + # If there are zero entries, or more than one: fail! We expected that + # exactly one is configured. require_matches_min: 1 require_matches_max: 1 -''' +""" -RETURN = ''' ---- +RETURN = r""" old_data: - description: - - A list of all elements for the current path before a change was made. - sample: - - '.id': '*1' - actual-interface: bridge - address: "192.168.88.1/24" - comment: defconf - disabled: false - dynamic: false - interface: bridge - invalid: false - network: 192.168.88.0 - type: list - elements: dict - returned: success + description: + - A list of all elements for the current path before a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: success new_data: - description: - - A list of all elements for the current path after a change was made. - sample: - - '.id': '*1' - actual-interface: bridge - address: "192.168.1.1/24" - comment: awesome - disabled: false - dynamic: false - interface: bridge - invalid: false - network: 192.168.1.0 - type: list - elements: dict - returned: success + description: + - A list of all elements for the current path after a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.1.1/24" + comment: awesome + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.1.0 + type: list + elements: dict + returned: success match_count: - description: - - The number of entries that matched the criteria in O(find). - sample: 1 - type: int - returned: success + description: + - The number of entries that matched the criteria in O(find). + sample: 1 + type: int + returned: success modify__count: - description: - - The number of entries that were modified. - sample: 1 - type: int - returned: success -''' + description: + - The number of entries that were modified. + sample: 1 + type: int + returned: success +""" from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.text.converters import to_native diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 5b34463..f696548 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -8,8 +8,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: api_info author: - "Felix Fontein (@felixfontein)" @@ -18,12 +17,12 @@ version_added: 2.2.0 description: - Allows to retrieve information for a path using the API. - This can be used to backup a path to restore it with the M(community.routeros.api_modify) module. - - Entries are normalized, dynamic and builtin entries are not returned. Use the O(handle_disabled) and - O(hide_defaults) options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return - dynamic resp. builtin entries, and use O(unfiltered) to return all fields including counters. - - B(Note) that this module is still heavily in development, and only supports B(some) paths. - If you want to support new paths, or think you found problems with existing paths, please first - L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). + - Entries are normalized, dynamic and builtin entries are not returned. Use the O(handle_disabled) and O(hide_defaults) + options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return dynamic resp. builtin + entries, and use O(unfiltered) to return all fields including counters. + - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new + paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue + Tracker,https://github.com/ansible-collections/community.routeros/issues/). extends_documentation_fragment: - community.routeros.api - community.routeros.api.restrict @@ -43,225 +42,225 @@ options: type: str choices: # BEGIN PATH LIST - - caps-man aaa - - caps-man access-list - - caps-man channel - - caps-man configuration - - caps-man datapath - - caps-man manager - - caps-man manager interface - - caps-man provisioning - - caps-man security - - certificate settings - - interface bonding - - interface bridge - - interface bridge mlag - - interface bridge port - - interface bridge port-controller - - interface bridge port-extender - - interface bridge settings - - interface bridge vlan - - interface detect-internet - - interface eoip - - interface ethernet - - interface ethernet poe - - interface ethernet switch - - interface ethernet switch port - - interface gre - - interface gre6 - - interface l2tp-client - - interface l2tp-server server - - interface list - - interface list member - - interface ovpn-client - - interface ovpn-server server - - interface ppp-client - - interface pppoe-client - - interface pppoe-server server - - interface pptp-server server - - interface sstp-server server - - interface vlan - - interface vrrp - - interface wifi - - interface wifi aaa - - interface wifi access-list - - interface wifi cap - - interface wifi capsman - - interface wifi channel - - interface wifi configuration - - interface wifi datapath - - interface wifi interworking - - interface wifi provisioning - - interface wifi security - - interface wifi steering - - interface wifiwave2 - - interface wifiwave2 aaa - - interface wifiwave2 access-list - - interface wifiwave2 cap - - interface wifiwave2 capsman - - interface wifiwave2 channel - - interface wifiwave2 configuration - - interface wifiwave2 datapath - - interface wifiwave2 interworking - - interface wifiwave2 provisioning - - interface wifiwave2 security - - interface wifiwave2 steering - - interface wireguard - - interface wireguard peers - - interface wireless - - interface wireless align - - interface wireless cap - - interface wireless security-profiles - - interface wireless sniffer - - interface wireless snooper - - iot modbus - - ip accounting - - ip accounting web-access - - ip address - - ip arp - - ip cloud - - ip cloud advanced - - ip dhcp-client - - ip dhcp-client option - - ip dhcp-relay - - ip dhcp-server - - ip dhcp-server config - - ip dhcp-server lease - - ip dhcp-server matcher - - ip dhcp-server network - - ip dhcp-server option - - ip dhcp-server option sets - - ip dns - - ip dns adlist - - ip dns static - - ip firewall address-list - - ip firewall connection tracking - - ip firewall filter - - ip firewall layer7-protocol - - ip firewall mangle - - ip firewall nat - - ip firewall raw - - ip firewall service-port - - ip hotspot service-port - - ip ipsec identity - - ip ipsec peer - - ip ipsec policy - - ip ipsec profile - - ip ipsec proposal - - ip ipsec settings - - ip neighbor discovery-settings - - ip pool - - ip proxy - - ip route - - ip route rule - - ip route vrf - - ip service - - ip settings - - ip smb - - ip socks - - ip ssh - - ip tftp settings - - ip traffic-flow - - ip traffic-flow ipfix - - ip traffic-flow target - - ip upnp - - ip upnp interfaces - - ip vrf - - ipv6 address - - ipv6 dhcp-client - - ipv6 dhcp-server - - ipv6 dhcp-server option - - ipv6 firewall address-list - - ipv6 firewall filter - - ipv6 firewall mangle - - ipv6 firewall nat - - ipv6 firewall raw - - ipv6 nd - - ipv6 nd prefix - - ipv6 nd prefix default - - ipv6 route - - ipv6 settings - - mpls - - mpls interface - - mpls ldp - - mpls ldp accept-filter - - mpls ldp advertise-filter - - mpls ldp interface - - port firmware - - port remote-access - - ppp aaa - - ppp profile - - ppp secret - - queue interface - - queue simple - - queue tree - - queue type - - radius - - radius incoming - - routing bgp aggregate - - routing bgp connection - - routing bgp instance - - routing bgp network - - routing bgp peer - - routing bgp template - - routing filter - - routing filter community-list - - routing filter num-list - - routing filter rule - - routing filter select-rule - - routing id - - routing igmp-proxy - - routing igmp-proxy interface - - routing mme - - routing ospf area - - routing ospf area range - - routing ospf instance - - routing ospf interface-template - - routing ospf static-neighbor - - routing pimsm instance - - routing pimsm interface-template - - routing rip - - routing ripng - - routing rule - - routing table - - snmp - - snmp community - - system clock - - system clock manual - - system health settings - - system identity - - system leds settings - - system logging - - system logging action - - system note - - system ntp client - - system ntp client servers - - system ntp server - - system package update - - system resource irq rps - - system routerboard settings - - system scheduler - - system script - - system upgrade mirror - - system ups - - system watchdog - - tool bandwidth-server - - tool e-mail - - tool graphing - - tool graphing interface - - tool graphing resource - - tool mac-server - - tool mac-server mac-winbox - - tool mac-server ping - - tool netwatch - - tool romon - - tool sms - - tool sniffer - - tool traffic-generator - - user - - user aaa - - user group - - user settings + - caps-man aaa + - caps-man access-list + - caps-man channel + - caps-man configuration + - caps-man datapath + - caps-man manager + - caps-man manager interface + - caps-man provisioning + - caps-man security + - certificate settings + - interface bonding + - interface bridge + - interface bridge mlag + - interface bridge port + - interface bridge port-controller + - interface bridge port-extender + - interface bridge settings + - interface bridge vlan + - interface detect-internet + - interface eoip + - interface ethernet + - interface ethernet poe + - interface ethernet switch + - interface ethernet switch port + - interface gre + - interface gre6 + - interface l2tp-client + - interface l2tp-server server + - interface list + - interface list member + - interface ovpn-client + - interface ovpn-server server + - interface ppp-client + - interface pppoe-client + - interface pppoe-server server + - interface pptp-server server + - interface sstp-server server + - interface vlan + - interface vrrp + - interface wifi + - interface wifi aaa + - interface wifi access-list + - interface wifi cap + - interface wifi capsman + - interface wifi channel + - interface wifi configuration + - interface wifi datapath + - interface wifi interworking + - interface wifi provisioning + - interface wifi security + - interface wifi steering + - interface wifiwave2 + - interface wifiwave2 aaa + - interface wifiwave2 access-list + - interface wifiwave2 cap + - interface wifiwave2 capsman + - interface wifiwave2 channel + - interface wifiwave2 configuration + - interface wifiwave2 datapath + - interface wifiwave2 interworking + - interface wifiwave2 provisioning + - interface wifiwave2 security + - interface wifiwave2 steering + - interface wireguard + - interface wireguard peers + - interface wireless + - interface wireless align + - interface wireless cap + - interface wireless security-profiles + - interface wireless sniffer + - interface wireless snooper + - iot modbus + - ip accounting + - ip accounting web-access + - ip address + - ip arp + - ip cloud + - ip cloud advanced + - ip dhcp-client + - ip dhcp-client option + - ip dhcp-relay + - ip dhcp-server + - ip dhcp-server config + - ip dhcp-server lease + - ip dhcp-server matcher + - ip dhcp-server network + - ip dhcp-server option + - ip dhcp-server option sets + - ip dns + - ip dns adlist + - ip dns static + - ip firewall address-list + - ip firewall connection tracking + - ip firewall filter + - ip firewall layer7-protocol + - ip firewall mangle + - ip firewall nat + - ip firewall raw + - ip firewall service-port + - ip hotspot service-port + - ip ipsec identity + - ip ipsec peer + - ip ipsec policy + - ip ipsec profile + - ip ipsec proposal + - ip ipsec settings + - ip neighbor discovery-settings + - ip pool + - ip proxy + - ip route + - ip route rule + - ip route vrf + - ip service + - ip settings + - ip smb + - ip socks + - ip ssh + - ip tftp settings + - ip traffic-flow + - ip traffic-flow ipfix + - ip traffic-flow target + - ip upnp + - ip upnp interfaces + - ip vrf + - ipv6 address + - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option + - ipv6 firewall address-list + - ipv6 firewall filter + - ipv6 firewall mangle + - ipv6 firewall nat + - ipv6 firewall raw + - ipv6 nd + - ipv6 nd prefix + - ipv6 nd prefix default + - ipv6 route + - ipv6 settings + - mpls + - mpls interface + - mpls ldp + - mpls ldp accept-filter + - mpls ldp advertise-filter + - mpls ldp interface + - port firmware + - port remote-access + - ppp aaa + - ppp profile + - ppp secret + - queue interface + - queue simple + - queue tree + - queue type + - radius + - radius incoming + - routing bgp aggregate + - routing bgp connection + - routing bgp instance + - routing bgp network + - routing bgp peer + - routing bgp template + - routing filter + - routing filter community-list + - routing filter num-list + - routing filter rule + - routing filter select-rule + - routing id + - routing igmp-proxy + - routing igmp-proxy interface + - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing ospf static-neighbor + - routing pimsm instance + - routing pimsm interface-template + - routing rip + - routing ripng + - routing rule + - routing table + - snmp + - snmp community + - system clock + - system clock manual + - system health settings + - system identity + - system leds settings + - system logging + - system logging action + - system note + - system ntp client + - system ntp client servers + - system ntp server + - system package update + - system resource irq rps + - system routerboard settings + - system scheduler + - system script + - system upgrade mirror + - system ups + - system watchdog + - tool bandwidth-server + - tool e-mail + - tool graphing + - tool graphing interface + - tool graphing resource + - tool mac-server + - tool mac-server mac-winbox + - tool mac-server ping + - tool netwatch + - tool romon + - tool sms + - tool sniffer + - tool traffic-generator + - user + - user aaa + - user group + - user settings # END PATH LIST unfiltered: description: @@ -317,10 +316,9 @@ seealso: - module: community.routeros.api_facts - module: community.routeros.api_find_and_modify - module: community.routeros.api_modify -''' +""" -EXAMPLES = ''' ---- +EXAMPLES = r""" - name: Get IP addresses community.routeros.api_info: hostname: "{{ hostname }}" @@ -344,26 +342,25 @@ EXAMPLES = ''' - name: Print data for IP addresses ansible.builtin.debug: var: ip_addresses.result -''' +""" -RETURN = ''' ---- +RETURN = r""" result: - description: A list of all elements for the current path. - sample: - - '.id': '*1' - actual-interface: bridge - address: "192.168.88.1/24" - comment: defconf - disabled: false - dynamic: false - interface: bridge - invalid: false - network: 192.168.88.0 - type: list - elements: dict - returned: always -''' + description: A list of all elements for the current path. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: always +""" from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.text.converters import to_native diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 9ab34d9..4abc8fc 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -8,8 +8,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: api_modify author: - "Felix Fontein (@felixfontein)" @@ -17,17 +16,17 @@ short_description: Modify data at paths with API version_added: 2.2.0 description: - Allows to modify information for a path using the API. - - Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way - depending on some search conditions. + - Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way depending + on some search conditions. - To make a backup of a path that can be restored with this module, use the M(community.routeros.api_info) module. - The module ignores dynamic and builtin entries. - - B(Note) that this module is still heavily in development, and only supports B(some) paths. - If you want to support new paths, or think you found problems with existing paths, please first - L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/). + - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new + paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue + Tracker,https://github.com/ansible-collections/community.routeros/issues/). notes: - - If write-only fields are present in the path, the module is B(not idempotent) in a strict sense, - since it is not able to verify the current value of these fields. The behavior the module should - assume can be controlled with the O(handle_write_only) option. + - If write-only fields are present in the path, the module is B(not idempotent) in a strict sense, since it is not able + to verify the current value of these fields. The behavior the module should assume can be controlled with the O(handle_write_only) + option. requirements: - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6 extends_documentation_fragment: @@ -47,230 +46,231 @@ options: path: description: - Path to query. - - An example value is V(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI. + - An example value is V(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS + CLI. required: true type: str choices: # BEGIN PATH LIST - - caps-man aaa - - caps-man access-list - - caps-man channel - - caps-man configuration - - caps-man datapath - - caps-man manager - - caps-man manager interface - - caps-man provisioning - - caps-man security - - certificate settings - - interface bonding - - interface bridge - - interface bridge mlag - - interface bridge port - - interface bridge port-controller - - interface bridge port-extender - - interface bridge settings - - interface bridge vlan - - interface detect-internet - - interface eoip - - interface ethernet - - interface ethernet poe - - interface ethernet switch - - interface ethernet switch port - - interface gre - - interface gre6 - - interface l2tp-client - - interface l2tp-server server - - interface list - - interface list member - - interface ovpn-client - - interface ovpn-server server - - interface ppp-client - - interface pppoe-client - - interface pppoe-server server - - interface pptp-server server - - interface sstp-server server - - interface vlan - - interface vrrp - - interface wifi - - interface wifi aaa - - interface wifi access-list - - interface wifi cap - - interface wifi capsman - - interface wifi channel - - interface wifi configuration - - interface wifi datapath - - interface wifi interworking - - interface wifi provisioning - - interface wifi security - - interface wifi steering - - interface wifiwave2 - - interface wifiwave2 aaa - - interface wifiwave2 access-list - - interface wifiwave2 cap - - interface wifiwave2 capsman - - interface wifiwave2 channel - - interface wifiwave2 configuration - - interface wifiwave2 datapath - - interface wifiwave2 interworking - - interface wifiwave2 provisioning - - interface wifiwave2 security - - interface wifiwave2 steering - - interface wireguard - - interface wireguard peers - - interface wireless - - interface wireless align - - interface wireless cap - - interface wireless security-profiles - - interface wireless sniffer - - interface wireless snooper - - iot modbus - - ip accounting - - ip accounting web-access - - ip address - - ip arp - - ip cloud - - ip cloud advanced - - ip dhcp-client - - ip dhcp-client option - - ip dhcp-relay - - ip dhcp-server - - ip dhcp-server config - - ip dhcp-server lease - - ip dhcp-server matcher - - ip dhcp-server network - - ip dhcp-server option - - ip dhcp-server option sets - - ip dns - - ip dns adlist - - ip dns static - - ip firewall address-list - - ip firewall connection tracking - - ip firewall filter - - ip firewall layer7-protocol - - ip firewall mangle - - ip firewall nat - - ip firewall raw - - ip firewall service-port - - ip hotspot service-port - - ip ipsec identity - - ip ipsec peer - - ip ipsec policy - - ip ipsec profile - - ip ipsec proposal - - ip ipsec settings - - ip neighbor discovery-settings - - ip pool - - ip proxy - - ip route - - ip route rule - - ip route vrf - - ip service - - ip settings - - ip smb - - ip socks - - ip ssh - - ip tftp settings - - ip traffic-flow - - ip traffic-flow ipfix - - ip traffic-flow target - - ip upnp - - ip upnp interfaces - - ip vrf - - ipv6 address - - ipv6 dhcp-client - - ipv6 dhcp-server - - ipv6 dhcp-server option - - ipv6 firewall address-list - - ipv6 firewall filter - - ipv6 firewall mangle - - ipv6 firewall nat - - ipv6 firewall raw - - ipv6 nd - - ipv6 nd prefix - - ipv6 nd prefix default - - ipv6 route - - ipv6 settings - - mpls - - mpls interface - - mpls ldp - - mpls ldp accept-filter - - mpls ldp advertise-filter - - mpls ldp interface - - port firmware - - port remote-access - - ppp aaa - - ppp profile - - ppp secret - - queue interface - - queue simple - - queue tree - - queue type - - radius - - radius incoming - - routing bgp aggregate - - routing bgp connection - - routing bgp instance - - routing bgp network - - routing bgp peer - - routing bgp template - - routing filter - - routing filter community-list - - routing filter num-list - - routing filter rule - - routing filter select-rule - - routing id - - routing igmp-proxy - - routing igmp-proxy interface - - routing mme - - routing ospf area - - routing ospf area range - - routing ospf instance - - routing ospf interface-template - - routing ospf static-neighbor - - routing pimsm instance - - routing pimsm interface-template - - routing rip - - routing ripng - - routing rule - - routing table - - snmp - - snmp community - - system clock - - system clock manual - - system health settings - - system identity - - system leds settings - - system logging - - system logging action - - system note - - system ntp client - - system ntp client servers - - system ntp server - - system package update - - system resource irq rps - - system routerboard settings - - system scheduler - - system script - - system upgrade mirror - - system ups - - system watchdog - - tool bandwidth-server - - tool e-mail - - tool graphing - - tool graphing interface - - tool graphing resource - - tool mac-server - - tool mac-server mac-winbox - - tool mac-server ping - - tool netwatch - - tool romon - - tool sms - - tool sniffer - - tool traffic-generator - - user - - user aaa - - user group - - user settings + - caps-man aaa + - caps-man access-list + - caps-man channel + - caps-man configuration + - caps-man datapath + - caps-man manager + - caps-man manager interface + - caps-man provisioning + - caps-man security + - certificate settings + - interface bonding + - interface bridge + - interface bridge mlag + - interface bridge port + - interface bridge port-controller + - interface bridge port-extender + - interface bridge settings + - interface bridge vlan + - interface detect-internet + - interface eoip + - interface ethernet + - interface ethernet poe + - interface ethernet switch + - interface ethernet switch port + - interface gre + - interface gre6 + - interface l2tp-client + - interface l2tp-server server + - interface list + - interface list member + - interface ovpn-client + - interface ovpn-server server + - interface ppp-client + - interface pppoe-client + - interface pppoe-server server + - interface pptp-server server + - interface sstp-server server + - interface vlan + - interface vrrp + - interface wifi + - interface wifi aaa + - interface wifi access-list + - interface wifi cap + - interface wifi capsman + - interface wifi channel + - interface wifi configuration + - interface wifi datapath + - interface wifi interworking + - interface wifi provisioning + - interface wifi security + - interface wifi steering + - interface wifiwave2 + - interface wifiwave2 aaa + - interface wifiwave2 access-list + - interface wifiwave2 cap + - interface wifiwave2 capsman + - interface wifiwave2 channel + - interface wifiwave2 configuration + - interface wifiwave2 datapath + - interface wifiwave2 interworking + - interface wifiwave2 provisioning + - interface wifiwave2 security + - interface wifiwave2 steering + - interface wireguard + - interface wireguard peers + - interface wireless + - interface wireless align + - interface wireless cap + - interface wireless security-profiles + - interface wireless sniffer + - interface wireless snooper + - iot modbus + - ip accounting + - ip accounting web-access + - ip address + - ip arp + - ip cloud + - ip cloud advanced + - ip dhcp-client + - ip dhcp-client option + - ip dhcp-relay + - ip dhcp-server + - ip dhcp-server config + - ip dhcp-server lease + - ip dhcp-server matcher + - ip dhcp-server network + - ip dhcp-server option + - ip dhcp-server option sets + - ip dns + - ip dns adlist + - ip dns static + - ip firewall address-list + - ip firewall connection tracking + - ip firewall filter + - ip firewall layer7-protocol + - ip firewall mangle + - ip firewall nat + - ip firewall raw + - ip firewall service-port + - ip hotspot service-port + - ip ipsec identity + - ip ipsec peer + - ip ipsec policy + - ip ipsec profile + - ip ipsec proposal + - ip ipsec settings + - ip neighbor discovery-settings + - ip pool + - ip proxy + - ip route + - ip route rule + - ip route vrf + - ip service + - ip settings + - ip smb + - ip socks + - ip ssh + - ip tftp settings + - ip traffic-flow + - ip traffic-flow ipfix + - ip traffic-flow target + - ip upnp + - ip upnp interfaces + - ip vrf + - ipv6 address + - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option + - ipv6 firewall address-list + - ipv6 firewall filter + - ipv6 firewall mangle + - ipv6 firewall nat + - ipv6 firewall raw + - ipv6 nd + - ipv6 nd prefix + - ipv6 nd prefix default + - ipv6 route + - ipv6 settings + - mpls + - mpls interface + - mpls ldp + - mpls ldp accept-filter + - mpls ldp advertise-filter + - mpls ldp interface + - port firmware + - port remote-access + - ppp aaa + - ppp profile + - ppp secret + - queue interface + - queue simple + - queue tree + - queue type + - radius + - radius incoming + - routing bgp aggregate + - routing bgp connection + - routing bgp instance + - routing bgp network + - routing bgp peer + - routing bgp template + - routing filter + - routing filter community-list + - routing filter num-list + - routing filter rule + - routing filter select-rule + - routing id + - routing igmp-proxy + - routing igmp-proxy interface + - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing ospf static-neighbor + - routing pimsm instance + - routing pimsm interface-template + - routing rip + - routing ripng + - routing rule + - routing table + - snmp + - snmp community + - system clock + - system clock manual + - system health settings + - system identity + - system leds settings + - system logging + - system logging action + - system note + - system ntp client + - system ntp client servers + - system ntp server + - system package update + - system resource irq rps + - system routerboard settings + - system scheduler + - system script + - system upgrade mirror + - system ups + - system watchdog + - tool bandwidth-server + - tool e-mail + - tool graphing + - tool graphing interface + - tool graphing resource + - tool mac-server + - tool mac-server mac-winbox + - tool mac-server ping + - tool netwatch + - tool romon + - tool sms + - tool sniffer + - tool traffic-generator + - user + - user aaa + - user group + - user settings # END PATH LIST data: description: @@ -298,12 +298,12 @@ options: default: ignore handle_entries_content: description: - - For a single entry in O(data), this describes how to handle fields that are not mentioned - in that entry, but appear in the actual config. + - For a single entry in O(data), this describes how to handle fields that are not mentioned in that entry, but appear + in the actual config. - If V(ignore), they are not modified. - If V(remove), they are removed. If at least one cannot be removed, the module will fail. - - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that - cannot be removed will be kept. + - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that cannot be removed will be + kept. - Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields. type: str choices: @@ -315,8 +315,8 @@ options: description: - How to handle values passed in for read-only fields. - If V(ignore), they are not passed to the API. - - If V(validate), the values are not passed for creation, and for updating they are compared to the value returned for the object. - If they differ, the module fails. + - If V(validate), the values are not passed for creation, and for updating they are compared to the value returned for + the object. If they differ, the module fails. - If V(error), the module will fail if read-only fields are provided. type: str choices: @@ -329,9 +329,8 @@ options: description: - How to handle values passed in for write-only fields. - If V(create_only), they are passed on creation, and ignored for updating. - - If V(always_update), they are always passed to the API. This means that if such a value is present, - the module will always result in C(changed) since there is no way to validate whether the value - actually changed. + - If V(always_update), they are always passed to the API. This means that if such a value is present, the module will + always result in C(changed) since there is no way to validate whether the value actually changed. - If V(error), the module will fail if write-only fields are provided. type: str choices: @@ -343,21 +342,18 @@ options: restrict: description: - Restrict operation to entries matching the following criteria. - - This can be useful together with O(handle_absent_entries=remove) to operate on a subset of - the values. - - For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and - O(restrict[].values=input) to restrict operation to the input chain, and ignore the - forward and output chains. + - This can be useful together with O(handle_absent_entries=remove) to operate on a subset of the values. + - For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and O(restrict[].values=input) + to restrict operation to the input chain, and ignore the forward and output chains. version_added: 2.18.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts - module: community.routeros.api_find_and_modify - module: community.routeros.api_info -''' +""" -EXAMPLES = ''' ---- +EXAMPLES = r""" - name: Setup DHCP server networks # Ensures that we have exactly two DHCP server networks (in the specified order) community.routeros.api_modify: @@ -411,43 +407,42 @@ EXAMPLES = ''' data: - action: drop chain: input -''' +""" -RETURN = ''' ---- +RETURN = r""" old_data: - description: - - A list of all elements for the current path before a change was made. - sample: - - '.id': '*1' - actual-interface: bridge - address: "192.168.88.1/24" - comment: defconf - disabled: false - dynamic: false - interface: bridge - invalid: false - network: 192.168.88.0 - type: list - elements: dict - returned: always + description: + - A list of all elements for the current path before a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.88.1/24" + comment: defconf + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.88.0 + type: list + elements: dict + returned: always new_data: - description: - - A list of all elements for the current path after a change was made. - sample: - - '.id': '*1' - actual-interface: bridge - address: "192.168.1.1/24" - comment: awesome - disabled: false - dynamic: false - interface: bridge - invalid: false - network: 192.168.1.0 - type: list - elements: dict - returned: always -''' + description: + - A list of all elements for the current path after a change was made. + sample: + - '.id': '*1' + actual-interface: bridge + address: "192.168.1.1/24" + comment: awesome + disabled: false + dynamic: false + interface: bridge + invalid: false + network: 192.168.1.0 + type: list + elements: dict + returned: always +""" from collections import defaultdict diff --git a/plugins/modules/command.py b/plugins/modules/command.py index bf74d47..306f648 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -7,27 +7,23 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: command author: "Egor Zaitsev (@heuels)" short_description: Run commands on remote devices running MikroTik RouterOS description: - - Sends arbitrary commands to an RouterOS node and returns the results - read from the device. This module includes an - argument that will cause the module to wait for a specific condition - before returning or timing out if the condition is not met. - - The module always indicates a (changed) status. You can use - R(the changed_when task property,override_the_changed_result) to determine - whether a command task actually resulted in a change or not. + - Sends arbitrary commands to an RouterOS node and returns the results read from the device. This module includes an argument + that will cause the module to wait for a specific condition before returning or timing out if the condition is not met. + - The module always indicates a (changed) status. You can use R(the changed_when task property,override_the_changed_result) + to determine whether a command task actually resulted in a change or not. extends_documentation_fragment: - community.routeros.attributes attributes: check_mode: support: none details: - - Before community.routeros 3.0.0, the module claimed to support check mode. - It simply executed the command in check mode. + - Before community.routeros 3.0.0, the module claimed to support check mode. It simply executed the command in check + mode. diff_mode: support: none platform: @@ -36,58 +32,47 @@ attributes: options: commands: description: - - List of commands to send to the remote RouterOS device over the - configured provider. The resulting output from the command - is returned. If the O(wait_for) argument is provided, the - module is not returned until the condition is satisfied or - the number of retries has expired. + - List of commands to send to the remote RouterOS device over the configured provider. The resulting output from the + command is returned. If the O(wait_for) argument is provided, the module is not returned until the condition is satisfied + or the number of retries has expired. required: true type: list elements: str wait_for: description: - - List of conditions to evaluate against the output of the - command. The task will wait for each condition to be true - before moving forward. If the conditional is not true - within the configured number of retries, the task fails. - See examples. + - List of conditions to evaluate against the output of the command. The task will wait for each condition to be true + before moving forward. If the conditional is not true within the configured number of retries, the task fails. See + examples. type: list elements: str match: description: - - The O(match) argument is used in conjunction with the - O(wait_for) argument to specify the match policy. Valid - values are V(all) or V(any). If the value is set to V(all) - then all conditionals in the wait_for must be satisfied. If - the value is set to V(any) then only one of the values must be - satisfied. + - The O(match) argument is used in conjunction with the O(wait_for) argument to specify the match policy. Valid values + are V(all) or V(any). If the value is set to V(all) then all conditionals in the wait_for must be satisfied. If the + value is set to V(any) then only one of the values must be satisfied. default: all choices: ['any', 'all'] type: str retries: description: - - Specifies the number of retries a command should by tried - before it is considered failed. The command is run on the - target device every retry and evaluated against the - O(wait_for) conditions. + - Specifies the number of retries a command should by tried before it is considered failed. The command is run on the + target device every retry and evaluated against the O(wait_for) conditions. default: 10 type: int interval: description: - - Configures the interval in seconds to wait between retries - of the command. If the command does not pass the specified - conditions, the interval indicates how long to wait before - trying the command again. + - Configures the interval in seconds to wait between retries of the command. If the command does not pass the specified + conditions, the interval indicates how long to wait before trying the command again. default: 1 type: int seealso: - ref: ansible_collections.community.routeros.docsite.ssh-guide - description: How to connect to RouterOS devices with SSH + description: How to connect to RouterOS devices with SSH. - ref: ansible_collections.community.routeros.docsite.quoting - description: How to quote and unquote commands and arguments -''' + description: How to quote and unquote commands and arguments. +""" -EXAMPLES = """ +EXAMPLES = r""" - name: Run command on remote devices community.routeros.command: commands: /system routerboard print @@ -113,19 +98,19 @@ EXAMPLES = """ - result[1] contains ether1 """ -RETURN = """ +RETURN = r""" stdout: - description: The set of responses from the commands + description: The set of responses from the commands. returned: always apart from low level errors (such as action plugin) type: list sample: ['...', '...'] stdout_lines: - description: The value of stdout split into a list + description: The value of stdout split into a list. returned: always apart from low level errors (such as action plugin) type: list sample: [['...', '...'], ['...'], ['...']] failed_conditions: - description: The list of conditionals that have failed + description: The list of conditionals that have failed. returned: failed type: list sample: ['...', '...'] diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 50f9a21..21013aa 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -7,16 +7,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -DOCUMENTATION = ''' ---- +DOCUMENTATION = r""" module: facts author: "Egor Zaitsev (@heuels)" short_description: Collect facts from remote devices running MikroTik RouterOS description: - - Collects a base set of device facts from a remote device that - is running RouterOS. This module prepends all of the - base network fact keys with C(ansible_net_). The facts - module will always collect a base set of facts from the device + - Collects a base set of device facts from a remote device that is running RouterOS. This module prepends all of the base + network fact keys with C(ansible_net_). The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. extends_documentation_fragment: - community.routeros.attributes @@ -29,12 +26,10 @@ attributes: options: gather_subset: description: - - When supplied, this argument will restrict the facts collected - to a given subset. Possible values for this argument include - V(all), V(hardware), V(config), V(interfaces), and V(routing). - - Can specify a list of values to include a larger subset. - Values can also be used with an initial V(!) to specify that a - specific subset should not be collected. + - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument + include V(all), V(hardware), V(config), V(interfaces), and V(routing). + - Can specify a list of values to include a larger subset. Values can also be used with an initial V(!) to specify that + a specific subset should not be collected. required: false default: - '!config' @@ -42,10 +37,10 @@ options: elements: str seealso: - ref: ansible_collections.community.routeros.docsite.ssh-guide - description: How to connect to RouterOS devices with SSH -''' + description: How to connect to RouterOS devices with SSH. +""" -EXAMPLES = """ +EXAMPLES = r""" - name: Collect all facts from the device community.routeros.facts: gather_subset: all @@ -61,7 +56,7 @@ EXAMPLES = """ - "!hardware" """ -RETURN = """ +RETURN = r""" ansible_facts: description: "Dictionary of IP geolocation facts for a host's IP address." returned: always @@ -129,9 +124,9 @@ ansible_facts: ansible_net_config_nonverbose: description: - The current active config from the device in minimal form. - - This value is idempotent in the sense that if the facts module is run twice and the device's config - was not changed between the runs, the value is identical. This is achieved by running C(/export) - and stripping the timestamp from the comment in the first line. + - This value is idempotent in the sense that if the facts module is run twice and the device's config was not changed + between the runs, the value is identical. This is achieved by running C(/export) and stripping the timestamp from + the comment in the first line. returned: O(gather_subset) contains V(config) type: str version_added: 1.2.0 diff --git a/update-docs.py b/update-docs.py index 05a9ee7..4f164c8 100755 --- a/update-docs.py +++ b/update-docs.py @@ -42,7 +42,7 @@ def main(): path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if path_info.fully_understood]) for file in MODULES: - update_file(file, ' # BEGIN PATH LIST', ' # END PATH LIST', ' - {choice}', path_choices) + update_file(file, ' # BEGIN PATH LIST', ' # END PATH LIST', ' - {choice}', path_choices) if __name__ == '__main__': From 1e0c582b9811f4923af36a7ab7fd3f43bf0b8d49 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 28 Dec 2024 16:52:27 +0100 Subject: [PATCH 295/365] Improve formulations. --- plugins/cliconf/routeros.py | 2 +- plugins/doc_fragments/api.py | 2 +- plugins/modules/api.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/cliconf/routeros.py b/plugins/cliconf/routeros.py index 1c3288f..dc2f4a9 100644 --- a/plugins/cliconf/routeros.py +++ b/plugins/cliconf/routeros.py @@ -10,7 +10,7 @@ author: "Egor Zaitsev (@heuels)" name: routeros short_description: Use routeros cliconf to run command on MikroTik RouterOS platform description: - - This routeros plugin provides low level abstraction apis for sending and receiving CLI commands from MikroTik RouterOS + - This routeros plugin provides low level abstraction APIs for sending and receiving CLI commands from MikroTik RouterOS network devices. """ diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index edef5f0..5b0b411 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -43,7 +43,7 @@ options: - ssl port: description: - - RouterOS api port. If O(tls) is set, port will apply to TLS/SSL connection. + - RouterOS API port. If O(tls) is set, port will apply to TLS/SSL connection. - Defaults are V(8728) for the HTTP API, and V(8729) for the HTTPS API. type: int force_no_cert: diff --git a/plugins/modules/api.py b/plugins/modules/api.py index ecd99e0..404569d 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -14,7 +14,7 @@ author: "Nikolay Dachev (@NikolayDachev)" short_description: Ansible module for RouterOS API description: - Ansible module for RouterOS API with the Python C(librouteros) library. - - This module can add, remove, update, query and execute arbitrary command in RouterOS via API. + - This module can add, remove, update, query, and execute arbitrary command in RouterOS through the API. notes: - O(add), O(remove), O(update), O(cmd), and O(query) are mutually exclusive. - Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules for more specific modifications, @@ -37,7 +37,7 @@ options: path: description: - Main path for all other arguments. - - If other arguments are not set, api will return all items in selected path. + - If other arguments are not set, the module will return all items in selected path. - Example V(ip address). Equivalent of RouterOS CLI C(/ip address print). required: true type: str @@ -57,7 +57,7 @@ options: update: description: - Update config/value in RouterOS by '.id' in selected path. - - Example V(.id=*03 address=1.1.1.3/32) and path V(ip address) will replace existing ip address with C(.id=*03). + - Example V(.id=*03 address=1.1.1.3/32) and path V(ip address) will replace the existing IP address with C(.id=*03). - Equivalent in RouterOS CLI C(/ip address set address=1.1.1.3/32 numbers=1). - Note C(number) in RouterOS CLI is different from C(.id). type: str @@ -261,7 +261,7 @@ EXAMPLES = r""" RETURN = r""" message: - description: All outputs are in list with dictionary elements returned from RouterOS api. + description: All outputs are in list with dictionary elements returned from RouterOS API. sample: - address: 1.2.3.4 - address: 2.3.4.5 From 2a3460827dc2ed6dd28896e2e6f9341d4f218cbc Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 29 Dec 2024 15:48:00 +0100 Subject: [PATCH 296/365] Fix doc fragments indents. --- plugins/doc_fragments/attributes.py | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/plugins/doc_fragments/attributes.py b/plugins/doc_fragments/attributes.py index 8c5c145..d4f407f 100644 --- a/plugins/doc_fragments/attributes.py +++ b/plugins/doc_fragments/attributes.py @@ -27,24 +27,24 @@ attributes: INFO_MODULE = r''' options: {} attributes: - check_mode: - support: full - details: - - This action does not modify state. - diff_mode: - support: N/A - details: - - This action does not modify state. + check_mode: + support: full + details: + - This action does not modify state. + diff_mode: + support: N/A + details: + - This action does not modify state. ''' ACTIONGROUP_API = r''' options: {} attributes: - action_group: - description: Use C(group/community.routeros.api) in C(module_defaults) to set defaults for this module. - support: full - membership: - - community.routeros.api + action_group: + description: Use C(group/community.routeros.api) in C(module_defaults) to set defaults for this module. + support: full + membership: + - community.routeros.api ''' CONN = r""" @@ -69,16 +69,16 @@ attributes: FACTS_MODULE = r''' options: {} attributes: - check_mode: - support: full - details: - - This action does not modify state. - diff_mode: - support: N/A - details: - - This action does not modify state. - facts: - support: full + check_mode: + support: full + details: + - This action does not modify state. + diff_mode: + support: N/A + details: + - This action does not modify state. + facts: + support: full ''' FILES = r""" From 44e6bb6f7a8839db42f574442973bbf600e1614b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 30 Dec 2024 21:11:17 +0100 Subject: [PATCH 297/365] Add 'idempotent' attribute (#337) * Add 'idempotent' attribute. * Mention check mode in attribute description. Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --------- Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --- plugins/doc_fragments/attributes.py | 14 ++++++++++++++ plugins/modules/api.py | 4 ++++ plugins/modules/api_facts.py | 1 + plugins/modules/api_find_and_modify.py | 2 ++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 2 ++ plugins/modules/command.py | 4 ++++ plugins/modules/facts.py | 1 + 8 files changed, 29 insertions(+) diff --git a/plugins/doc_fragments/attributes.py b/plugins/doc_fragments/attributes.py index d4f407f..b8e68bf 100644 --- a/plugins/doc_fragments/attributes.py +++ b/plugins/doc_fragments/attributes.py @@ -21,6 +21,20 @@ attributes: platform: description: Target OS/families that can be operated against. support: N/A + idempotent: + description: + - When run twice in a row outside check mode, with the same arguments, the second invocation indicates no change. + - This assumes that the system controlled/queried by the module has not changed in a relevant way. +""" + + # Should be used together with the standard fragment + IDEMPOTENT_NOT_MODIFY_STATE = r""" +options: {} +attributes: + idempotent: + support: full + details: + - This action does not modify state. """ # Should be used together with the standard fragment diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 404569d..7d90045 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -33,6 +33,10 @@ attributes: platforms: RouterOS action_group: version_added: 2.1.0 + idempotent: + support: N/A + details: + - Whether the executed command is idempotent depends on the operation performed. options: path: description: diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index e1fb70a..b6d1261 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -29,6 +29,7 @@ extends_documentation_fragment: - community.routeros.attributes.actiongroup_api - community.routeros.attributes.facts - community.routeros.attributes.facts_module + - community.routeros.attributes.idempotent_not_modify_state attributes: platform: support: full diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index f6aab9f..817451c 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -35,6 +35,8 @@ attributes: platform: support: full platforms: RouterOS + idempotent: + support: full options: path: description: diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index f696548..e68ded0 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -28,6 +28,7 @@ extends_documentation_fragment: - community.routeros.api.restrict - community.routeros.attributes - community.routeros.attributes.actiongroup_api + - community.routeros.attributes.idempotent_not_modify_state - community.routeros.attributes.info_module attributes: platform: diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 4abc8fc..b4a7765 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -42,6 +42,8 @@ attributes: platform: support: full platforms: RouterOS + idempotent: + support: full options: path: description: diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 306f648..90f9733 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -29,6 +29,10 @@ attributes: platform: support: full platforms: RouterOS + idempotent: + support: N/A + details: + - Whether the executed command is idempotent depends on the command. options: commands: description: diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 21013aa..7b169b7 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -19,6 +19,7 @@ extends_documentation_fragment: - community.routeros.attributes - community.routeros.attributes.facts - community.routeros.attributes.facts_module + - community.routeros.attributes.idempotent_not_modify_state attributes: platform: support: full From 71882863a51269990eceefaf3dd34295da43fd0b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 30 Dec 2024 21:13:39 +0100 Subject: [PATCH 298/365] Prepare 3.2.0 release. --- changelogs/fragments/3.2.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.2.0.yml diff --git a/changelogs/fragments/3.2.0.yml b/changelogs/fragments/3.2.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.2.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index e59c543..c05b819 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.1.0 +version: 3.2.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 4241179471fa7139e05ae118954d940b34c62712 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 30 Dec 2024 22:03:45 +0100 Subject: [PATCH 299/365] Release 3.2.0. --- CHANGELOG.md | 236 ++++++++++-------- CHANGELOG.rst | 13 + changelogs/changelog.yaml | 10 + changelogs/fragments/3.2.0.yml | 1 - .../331-add-routing-filter-community-list.yml | 2 - 5 files changed, 149 insertions(+), 113 deletions(-) delete mode 100644 changelogs/fragments/3.2.0.yml delete mode 100644 changelogs/fragments/331-add-routing-filter-community-list.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 135eb61..9105fc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,143 +2,159 @@ **Topics** -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.1\.0 + +## v3\.2\.0 ### Release Summary -Bugfix and feature release\. +Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. + + +## v3\.1\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -149,7 +165,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -167,12 +183,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -183,12 +199,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -200,12 +216,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -229,12 +245,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -244,12 +260,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -258,12 +274,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -280,12 +296,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -295,12 +311,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -314,12 +330,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -333,12 +349,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -353,12 +369,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -390,12 +406,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -409,7 +425,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -430,7 +446,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -443,7 +459,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -456,12 +472,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -481,12 +497,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -499,12 +515,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -519,12 +535,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -537,12 +553,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -581,7 +597,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -594,12 +610,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -614,7 +630,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -628,12 +644,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -652,12 +668,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -681,12 +697,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -722,12 +738,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -743,12 +759,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -757,7 +773,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -770,7 +786,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -783,7 +799,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -796,12 +812,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fdfeca0..4b28c9c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,19 @@ Community RouterOS Release Notes .. contents:: Topics +v3.2.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add support for the ``routing filter community-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/331). + v3.1.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 8522a87..1dd758d 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -824,3 +824,13 @@ releases: - 324-fix-firewall-log-and-log-prefix.yaml - 327-add-missing-ip-pool-fields.yml release_date: '2024-12-02' + 3.2.0: + changes: + minor_changes: + - api_info, api_modify - add support for the ``routing filter community-list`` + path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/331). + release_summary: Feature release. + fragments: + - 3.2.0.yml + - 331-add-routing-filter-community-list.yml + release_date: '2024-12-30' diff --git a/changelogs/fragments/3.2.0.yml b/changelogs/fragments/3.2.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.2.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/331-add-routing-filter-community-list.yml b/changelogs/fragments/331-add-routing-filter-community-list.yml deleted file mode 100644 index e4cb0ba..0000000 --- a/changelogs/fragments/331-add-routing-filter-community-list.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``routing filter community-list`` path implemented by RouterOS 7 and newer (https://github.com/ansible-collections/community.routeros/pull/331). From dcdca90dd02aec91abf9fd0a301515c4078fac40 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 3 Jan 2025 14:49:49 +0100 Subject: [PATCH 300/365] Add extra sanity test for routeros action group. --- tests/sanity/extra/action-group.json | 12 ++ tests/sanity/extra/action-group.json.license | 3 + tests/sanity/extra/action-group.py | 119 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/sanity/extra/action-group.json create mode 100644 tests/sanity/extra/action-group.json.license create mode 100755 tests/sanity/extra/action-group.py diff --git a/tests/sanity/extra/action-group.json b/tests/sanity/extra/action-group.json new file mode 100644 index 0000000..db6a92b --- /dev/null +++ b/tests/sanity/extra/action-group.json @@ -0,0 +1,12 @@ +{ + "include_symlinks": true, + "prefixes": [ + "meta/runtime.yml", + "plugins/modules/", + "tests/sanity/extra/action-group." + ], + "output": "path-message", + "requirements": [ + "pyyaml" + ] +} diff --git a/tests/sanity/extra/action-group.json.license b/tests/sanity/extra/action-group.json.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/extra/action-group.json.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/action-group.py b/tests/sanity/extra/action-group.py new file mode 100755 index 0000000..cc00945 --- /dev/null +++ b/tests/sanity/extra/action-group.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# Copyright (c) 2024, Felix Fontein +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +"""Make sure all modules that should show up in the action group.""" + +from __future__ import annotations + +import os +import re +import yaml + + +ACTION_GROUPS = { + # The format is as follows: + # * 'pattern': a regular expression matching all module names potentially belonging to the action group; + # * 'exclusions': a list of modules that are not part of the action group; all other modules matching 'pattern' must be part of it; + # * 'doc_fragment': the docs fragment that documents membership of the action group. + 'api': { + 'pattern': re.compile('^api.*$'), + 'exclusions': [], + 'doc_fragment': 'community.routeros.attributes.actiongroup_api', + }, +} + + +def main(): + """Main entry point.""" + + # Load redirects + meta_runtime = 'meta/runtime.yml' + self_path = 'tests/sanity/extra/action-group.py' + try: + with open(meta_runtime, 'rb') as f: + data = yaml.safe_load(f) + action_groups = data['action_groups'] + except Exception as exc: + print(f'{meta_runtime}: cannot load action groups: {exc}') + return + + for action_group in action_groups: + if action_group not in ACTION_GROUPS: + print(f'{meta_runtime}: found unknown action group {action_group!r}; likely {self_path} needs updating') + for action_group, action_group_data in list(ACTION_GROUPS.items()): + if action_group not in action_groups: + print(f'{meta_runtime}: cannot find action group {action_group!r}; likely {self_path} needs updating') + + modules_directory = 'plugins/modules/' + modules_suffix = '.py' + + for file in os.listdir(modules_directory): + if not file.endswith(modules_suffix): + continue + module_name = file[:-len(modules_suffix)] + + for action_group, action_group_data in ACTION_GROUPS.items(): + action_group_content = action_groups.get(action_group) or [] + path = os.path.join(modules_directory, file) + + if not action_group_data['pattern'].match(module_name): + if module_name in action_group_content: + print(f'{path}: module is in action group {action_group!r} despite not matching its pattern as defined in {self_path}') + continue + + should_be_in_action_group = module_name not in action_group_data['exclusions'] + + if should_be_in_action_group: + if module_name not in action_group_content: + print(f'{meta_runtime}: module {module_name!r} is not part of {action_group!r} action group') + else: + action_group_content.remove(module_name) + + documentation = [] + in_docs = False + with open(path, 'r', encoding='utf-8') as f: + for line in f: + if line.startswith('DOCUMENTATION ='): + in_docs = True + elif line.startswith(("'''", '"""')) and in_docs: + in_docs = False + elif in_docs: + documentation.append(line) + if in_docs: + print(f'{path}: cannot find DOCUMENTATION end') + if not documentation: + print(f'{path}: cannot find DOCUMENTATION') + continue + + try: + docs = yaml.safe_load('\n'.join(documentation)) + if not isinstance(docs, dict): + raise Exception('is not a top-level dictionary') + except Exception as exc: + print(f'{path}: cannot load DOCUMENTATION as YAML: {exc}') + continue + + docs_fragments = docs.get('extends_documentation_fragment') or [] + is_in_action_group = action_group_data['doc_fragment'] in docs_fragments + + if should_be_in_action_group != is_in_action_group: + if should_be_in_action_group: + print( + f'{path}: module does not document itself as part of action group {action_group!r}, but it should;' + f' you need to add {action_group_data["doc_fragment"]} to "extends_documentation_fragment" in DOCUMENTATION' + ) + else: + print(f'{path}: module documents itself as part of action group {action_group!r}, but it should not be') + + for action_group, action_group_data in ACTION_GROUPS.items(): + action_group_content = action_groups.get(action_group) or [] + for module_name in action_group_content: + print( + f'{meta_runtime}: module {module_name} mentioned in {action_group!r} action group' + f' does not exist or does not match pattern defined in {self_path}' + ) + + +if __name__ == '__main__': + main() From 1466c9f984e4570f8c4d530daa868e4348101dff Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 4 Jan 2025 11:25:03 +0100 Subject: [PATCH 301/365] Fix CI badge image URL. Add documentation badge. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f7b488d..bdea3c3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ SPDX-License-Identifier: GPL-3.0-or-later --> # 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) +[![Documentation](https://img.shields.io/badge/docs-brightgreen.svg)](https://docs.ansible.com/ansible/devel/collections/community/routeros/) +[![CI](https://github.com/ansible-collections/community.routeros/actions/workflows/ansible-test.yml/badge.svg?branch=main)](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) [![REUSE status](https://api.reuse.software/badge/github.com/ansible-collections/community.routeros)](https://api.reuse.software/info/github.com/ansible-collections/community.routeros) From 364ef6c5fea745ad58bf877da3688bc32212f8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Tue, 21 Jan 2025 20:48:38 +0100 Subject: [PATCH 302/365] Fixes #338: Add require-message-auth in radius path (#339) * Fixes #338: Add require-message-auth in radius path Add changelog fragment * Update changelogs/fragments/339-add-require-message-auth-for-radius.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- .../fragments/339-add-require-message-auth-for-radius.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/339-add-require-message-auth-for-radius.yml diff --git a/changelogs/fragments/339-add-require-message-auth-for-radius.yml b/changelogs/fragments/339-add-require-message-auth-for-radius.yml new file mode 100644 index 0000000..7ec322d --- /dev/null +++ b/changelogs/fragments/339-add-require-message-auth-for-radius.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add missing attribute ``require-message-auth`` for the ``radius`` path which exists since RouterOS version 7.15 (https://github.com/ansible-collections/community.routeros/issues/338, https://github.com/ansible-collections/community.routeros/pull/339). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 25dd4cb..da85dd3 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4018,6 +4018,9 @@ PATHS = { 'src-address': KeyInfo(default='0.0.0.0'), 'timeout': KeyInfo(default='300ms'), }, + versioned_fields=[ + ([('7.15', '>=')], 'require-message-auth', KeyInfo(default='yes-for-request-resp')), + ], ), ), ('radius', 'incoming'): APIData( From 11454b802e880ab19cebeb5c47bdf5aac5ae5128 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 21 Jan 2025 21:03:02 +0100 Subject: [PATCH 303/365] Prepare 3.3.0. --- changelogs/fragments/3.3.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.3.0.yml diff --git a/changelogs/fragments/3.3.0.yml b/changelogs/fragments/3.3.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.3.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index c05b819..f127f37 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.2.0 +version: 3.3.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 85d24d180ee4b0a21aaacece744b81e7b3b5444b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCnch?= Date: Fri, 24 Jan 2025 21:40:39 +0100 Subject: [PATCH 304/365] Fixes #284: Implement 'interface wireless access-list' and 'interface wireless connect-list' (#340) Add changelog fragment --- ...rface-wireless-access-and-connect-list.yml | 2 + plugins/module_utils/_api_data.py | 59 +++++++++++++++++++ plugins/modules/api_info.py | 2 + plugins/modules/api_modify.py | 2 + 4 files changed, 65 insertions(+) create mode 100644 changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml diff --git a/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml b/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml new file mode 100644 index 0000000..75b6b55 --- /dev/null +++ b/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add the ``interface wireless access-list`` and ``interface wireless connect-list`` paths (https://github.com/ansible-collections/community.routeros/issues/284, https://github.com/ansible-collections/community.routeros/pull/340). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index da85dd3..f88950c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2545,6 +2545,30 @@ PATHS = { }, ), ), + ('interface', 'wireless', 'access-list'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + 'allow-signal-out-of-range': KeyInfo(default='10s'), + 'ap-tx-limit': KeyInfo(default=0), + 'authentication': KeyInfo(default=True), + 'client-tx-limit': KeyInfo(default=0), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'forwarding': KeyInfo(default=True), + 'interface': KeyInfo(default='any'), + 'mac-address': KeyInfo(default='00:00:00:00:00:00'), + 'management-protection-key': KeyInfo(default=''), + 'private-algo': KeyInfo(default='none'), + 'private-key': KeyInfo(default=''), + 'private-pre-shared-key': KeyInfo(default=''), + 'signal-range': KeyInfo(default='-120..120'), + 'time': KeyInfo(), + 'vlan-id': KeyInfo(default=1), + 'vlan-mode': KeyInfo(default='default'), + }, + ), + ), ('interface', 'wireless', 'cap'): APIData( unversioned=VersionedAPIData( single_value=True, @@ -2563,6 +2587,41 @@ PATHS = { }, ), ), + ('interface', 'wireless', 'connect-list'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + fields={ + '3gpp': KeyInfo(default=''), + 'allow-signal-out-of-range': KeyInfo(default='10s'), + 'area-prefix': KeyInfo(default=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'connect': KeyInfo(default=True), + 'disabled': KeyInfo(default=False), + 'interface': KeyInfo(required=True), + 'interworking': KeyInfo(default='any'), + 'iw-asra': KeyInfo(default='any'), + 'iw-authentication-types': KeyInfo(), + 'iw-connection-capabilities': KeyInfo(), + 'iw-esr': KeyInfo(default='any'), + 'iw-hessid': KeyInfo(default='00:00:00:00:00:00'), + 'iw-hotspot20': KeyInfo(default='any'), + 'iw-hotspot20-dgaf': KeyInfo(default='any'), + 'iw-internet': KeyInfo(default='any'), + 'iw-ipv4-availability': KeyInfo(default='any'), + 'iw-ipv6-availability': KeyInfo(default='any'), + 'iw-network-type': KeyInfo(default='wildcard'), + 'iw-realms': KeyInfo(), + 'iw-roaming-ois': KeyInfo(default=''), + 'iw-uesa': KeyInfo(default='any'), + 'iw-venue': KeyInfo(default='any'), + 'mac-address': KeyInfo(default='00:00:00:00:00:00'), + 'security-profile': KeyInfo(default='none'), + 'signal-range': KeyInfo(default='-120..120'), + 'ssid': KeyInfo(default=''), + 'wireless-protocol': KeyInfo(default='any'), + }, + ), + ), ('interface', 'wireless', 'security-profiles'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index e68ded0..b4af74c 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -109,8 +109,10 @@ options: - interface wireguard - interface wireguard peers - interface wireless + - interface wireless access-list - interface wireless align - interface wireless cap + - interface wireless connect-list - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index b4a7765..f0ac26d 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -120,8 +120,10 @@ options: - interface wireguard - interface wireguard peers - interface wireless + - interface wireless access-list - interface wireless align - interface wireless cap + - interface wireless connect-list - interface wireless security-profiles - interface wireless sniffer - interface wireless snooper From 575af30d88d52cacb3b10b110e97803e20206da9 Mon Sep 17 00:00:00 2001 From: Peter Petrovich Date: Sun, 26 Jan 2025 12:34:43 +0100 Subject: [PATCH 305/365] DHCPv6 client: add new options from 7.15+ (#341) * script * custom-duid * use-interface-duid * validate-server-duid --- .../341-add-dhcpv6-client-use-interface-duid.yml | 2 ++ plugins/module_utils/_api_data.py | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml diff --git a/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml b/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml new file mode 100644 index 0000000..f034497 --- /dev/null +++ b/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add the ``use-interface-duid`` option for ``ipv6 dhcp-client`` path. This option prevents issues with Fritzbox modems and routers, when using virtual interfaces (like VLANs) may create duplicated records in hosts config, this breaks original "expose-host" function. Also add the ``script``, ``custom-duid`` and ``validate-server-duid`` as backport from 7.15 version update (https://github.com/ansible-collections/community.routeros/pull/341). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index f88950c..fc50f4c 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3544,6 +3544,14 @@ PATHS = { 'request': KeyInfo(), 'use-peer-dns': KeyInfo(default=True), }, + versioned_fields=[ + # Mikrotik does not provide exact version in official changelogs. + # The 7.15 version is the earliest, found option in router config backups: + ([('7.15', '>=')], 'script', KeyInfo(default='')), + ([('7.15', '>=')], 'custom-duid', KeyInfo(default='')), + ([('7.15', '>=')], 'use-interface-duid', KeyInfo(default=False)), + ([('7.15', '>=')], 'validate-server-duid', KeyInfo(default=True)), + ], ), ), ('ipv6', 'dhcp-server'): APIData( From 388366542dc18946e265b757d719ed0156eb9f61 Mon Sep 17 00:00:00 2001 From: Peter Petrovich Date: Sun, 26 Jan 2025 12:52:36 +0100 Subject: [PATCH 306/365] Add 'interface 6to4' path, allows manage 6to4 tunnels like HE (#342) --- .../fragments/342-add-interface-6to4.yml | 2 ++ plugins/module_utils/_api_data.py | 19 +++++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 23 insertions(+) create mode 100644 changelogs/fragments/342-add-interface-6to4.yml diff --git a/changelogs/fragments/342-add-interface-6to4.yml b/changelogs/fragments/342-add-interface-6to4.yml new file mode 100644 index 0000000..09396bb --- /dev/null +++ b/changelogs/fragments/342-add-interface-6to4.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add the ``interface 6to4`` path. Used to manage IPv6 tunnels via tunnel-brokers like HE, where native IPv6 is not provided (https://github.com/ansible-collections/community.routeros/pull/342). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fc50f4c..ce5c555 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -226,6 +226,25 @@ def join_path(path): # 3. All bold attributes go into the `primary_keys` list -- this is not always true! PATHS = { + ('interface', '6to4'): APIData( + unversioned=VersionedAPIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'clamp-tcp-mss': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dont-fragment': KeyInfo(default=False), + 'dscp': KeyInfo(default='inherit'), + 'ipsec-secret': KeyInfo(can_disable=True), + 'keepalive': KeyInfo(default='10s,10', can_disable=True), + 'local-address': KeyInfo(default='0.0.0.0'), + 'mtu': KeyInfo(default='auto'), + 'name': KeyInfo(), + 'remote-address': KeyInfo(required=True), + } + ), + ), ('interface', 'bonding'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index b4af74c..346a317 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -53,6 +53,7 @@ options: - caps-man provisioning - caps-man security - certificate settings + - interface 6to4 - interface bonding - interface bridge - interface bridge mlag diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index f0ac26d..ef50293 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -64,6 +64,7 @@ options: - caps-man provisioning - caps-man security - certificate settings + - interface 6to4 - interface bonding - interface bridge - interface bridge mlag From f6d50f8cc570c5c761d115ae4007713d3869c19e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 27 Jan 2025 05:32:10 +0100 Subject: [PATCH 307/365] Release 3.3.0. --- CHANGELOG.md | 243 ++++++++++-------- CHANGELOG.rst | 16 ++ changelogs/changelog.yaml | 25 ++ changelogs/fragments/3.3.0.yml | 1 - ...39-add-require-message-auth-for-radius.yml | 2 - ...rface-wireless-access-and-connect-list.yml | 2 - ...1-add-dhcpv6-client-use-interface-duid.yml | 2 - .../fragments/342-add-interface-6to4.yml | 2 - 8 files changed, 172 insertions(+), 121 deletions(-) delete mode 100644 changelogs/fragments/3.3.0.yml delete mode 100644 changelogs/fragments/339-add-require-message-auth-for-radius.yml delete mode 100644 changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml delete mode 100644 changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml delete mode 100644 changelogs/fragments/342-add-interface-6to4.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 9105fc0..3458fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,137 +2,140 @@ **Topics** -- v3\.2\.0 +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.2\.0 + +## v3\.3\.0 ### Release Summary @@ -142,17 +145,33 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. +* api\_info\, api\_modify \- add the interface 6to4 path\. Used to manage IPv6 tunnels via tunnel\-brokers like HE\, where native IPv6 is not provided \([https\://github\.com/ansible\-collections/community\.routeros/pull/342](https\://github\.com/ansible\-collections/community\.routeros/pull/342)\)\. +* api\_info\, api\_modify \- add the interface wireless access\-list and interface wireless connect\-list paths \([https\://github\.com/ansible\-collections/community\.routeros/issues/284](https\://github\.com/ansible\-collections/community\.routeros/issues/284)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/340](https\://github\.com/ansible\-collections/community\.routeros/pull/340)\)\. +* api\_info\, api\_modify \- add the use\-interface\-duid option for ipv6 dhcp\-client path\. This option prevents issues with Fritzbox modems and routers\, when using virtual interfaces \(like VLANs\) may create duplicated records in hosts config\, this breaks original \"expose\-host\" function\. Also add the script\, custom\-duid and validate\-server\-duid as backport from 7\.15 version update \([https\://github\.com/ansible\-collections/community\.routeros/pull/341](https\://github\.com/ansible\-collections/community\.routeros/pull/341)\)\. + + +## v3\.2\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -165,7 +184,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -183,12 +202,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -199,12 +218,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -216,12 +235,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -245,12 +264,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -260,12 +279,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -274,12 +293,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -296,12 +315,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -311,12 +330,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -330,12 +349,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -349,12 +368,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -369,12 +388,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -406,12 +425,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -425,7 +444,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -446,7 +465,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -459,7 +478,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -472,12 +491,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -497,12 +516,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -515,12 +534,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -535,12 +554,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -553,12 +572,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -597,7 +616,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -610,12 +629,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -630,7 +649,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -644,12 +663,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -668,12 +687,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -697,12 +716,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -738,12 +757,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -759,12 +778,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -773,7 +792,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -786,7 +805,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -799,7 +818,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -812,12 +831,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4b28c9c..8b57038 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,22 @@ Community RouterOS Release Notes .. contents:: Topics +v3.3.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add missing attribute ``require-message-auth`` for the ``radius`` path which exists since RouterOS version 7.15 (https://github.com/ansible-collections/community.routeros/issues/338, https://github.com/ansible-collections/community.routeros/pull/339). +- api_info, api_modify - add the ``interface 6to4`` path. Used to manage IPv6 tunnels via tunnel-brokers like HE, where native IPv6 is not provided (https://github.com/ansible-collections/community.routeros/pull/342). +- api_info, api_modify - add the ``interface wireless access-list`` and ``interface wireless connect-list`` paths (https://github.com/ansible-collections/community.routeros/issues/284, https://github.com/ansible-collections/community.routeros/pull/340). +- api_info, api_modify - add the ``use-interface-duid`` option for ``ipv6 dhcp-client`` path. This option prevents issues with Fritzbox modems and routers, when using virtual interfaces (like VLANs) may create duplicated records in hosts config, this breaks original "expose-host" function. Also add the ``script``, ``custom-duid`` and ``validate-server-duid`` as backport from 7.15 version update (https://github.com/ansible-collections/community.routeros/pull/341). + v3.2.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 1dd758d..a4fa82f 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -834,3 +834,28 @@ releases: - 3.2.0.yml - 331-add-routing-filter-community-list.yml release_date: '2024-12-30' + 3.3.0: + changes: + minor_changes: + - api_info, api_modify - add missing attribute ``require-message-auth`` for + the ``radius`` path which exists since RouterOS version 7.15 (https://github.com/ansible-collections/community.routeros/issues/338, + https://github.com/ansible-collections/community.routeros/pull/339). + - api_info, api_modify - add the ``interface 6to4`` path. Used to manage IPv6 + tunnels via tunnel-brokers like HE, where native IPv6 is not provided (https://github.com/ansible-collections/community.routeros/pull/342). + - api_info, api_modify - add the ``interface wireless access-list`` and ``interface + wireless connect-list`` paths (https://github.com/ansible-collections/community.routeros/issues/284, + https://github.com/ansible-collections/community.routeros/pull/340). + - api_info, api_modify - add the ``use-interface-duid`` option for ``ipv6 + dhcp-client`` path. This option prevents issues with Fritzbox modems and + routers, when using virtual interfaces (like VLANs) may create duplicated + records in hosts config, this breaks original "expose-host" function. Also + add the ``script``, ``custom-duid`` and ``validate-server-duid`` as backport + from 7.15 version update (https://github.com/ansible-collections/community.routeros/pull/341). + release_summary: Feature release. + fragments: + - 3.3.0.yml + - 339-add-require-message-auth-for-radius.yml + - 340-add-interface-wireless-access-and-connect-list.yml + - 341-add-dhcpv6-client-use-interface-duid.yml + - 342-add-interface-6to4.yml + release_date: '2025-01-27' diff --git a/changelogs/fragments/3.3.0.yml b/changelogs/fragments/3.3.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.3.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/339-add-require-message-auth-for-radius.yml b/changelogs/fragments/339-add-require-message-auth-for-radius.yml deleted file mode 100644 index 7ec322d..0000000 --- a/changelogs/fragments/339-add-require-message-auth-for-radius.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add missing attribute ``require-message-auth`` for the ``radius`` path which exists since RouterOS version 7.15 (https://github.com/ansible-collections/community.routeros/issues/338, https://github.com/ansible-collections/community.routeros/pull/339). diff --git a/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml b/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml deleted file mode 100644 index 75b6b55..0000000 --- a/changelogs/fragments/340-add-interface-wireless-access-and-connect-list.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add the ``interface wireless access-list`` and ``interface wireless connect-list`` paths (https://github.com/ansible-collections/community.routeros/issues/284, https://github.com/ansible-collections/community.routeros/pull/340). diff --git a/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml b/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml deleted file mode 100644 index f034497..0000000 --- a/changelogs/fragments/341-add-dhcpv6-client-use-interface-duid.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add the ``use-interface-duid`` option for ``ipv6 dhcp-client`` path. This option prevents issues with Fritzbox modems and routers, when using virtual interfaces (like VLANs) may create duplicated records in hosts config, this breaks original "expose-host" function. Also add the ``script``, ``custom-duid`` and ``validate-server-duid`` as backport from 7.15 version update (https://github.com/ansible-collections/community.routeros/pull/341). diff --git a/changelogs/fragments/342-add-interface-6to4.yml b/changelogs/fragments/342-add-interface-6to4.yml deleted file mode 100644 index 09396bb..0000000 --- a/changelogs/fragments/342-add-interface-6to4.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add the ``interface 6to4`` path. Used to manage IPv6 tunnels via tunnel-brokers like HE, where native IPv6 is not provided (https://github.com/ansible-collections/community.routeros/pull/342). From a9f787fd761894da248a4d9bef079a9c3717ca9c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 11 Feb 2025 22:50:43 +0100 Subject: [PATCH 308/365] Clean up workflow. --- .github/workflows/ansible-test.yml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 4431bea..fa0a9cb 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -36,15 +36,12 @@ jobs: # image for these stable branches. The list of branches where this is necessary will # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 # for the latest list. - runs-on: >- - ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11"]' - ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} + runs-on: ubuntu-latest steps: - name: Perform sanity testing uses: felixfontein/ansible-test-gh-action@main with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: sanity @@ -58,10 +55,7 @@ jobs: # image for these stable branches. The list of branches where this is necessary will # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 # for the latest list. - runs-on: >- - ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11"]' - ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} + runs-on: ubuntu-latest name: Units (Ⓐ${{ matrix.ansible }}) strategy: # As soon as the first unit test fails, cancel the others to free up the CI queue @@ -79,7 +73,7 @@ jobs: Ansible version ${{ matrix.ansible }} uses: felixfontein/ansible-test-gh-action@main with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} testing-type: units @@ -93,10 +87,7 @@ jobs: # image for these stable branches. The list of branches where this is necessary will # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 # for the latest list. - runs-on: >- - ${{ contains(fromJson( - '["stable-2.9", "stable-2.10", "stable-2.11"]' - ), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }} + runs-on: ubuntu-latest name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: fail-fast: false @@ -133,7 +124,7 @@ jobs: under Python ${{ matrix.python }} uses: felixfontein/ansible-test-gh-action@main with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.9", "stable-2.10", "stable-2.11"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} + ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} ansible-core-version: ${{ matrix.ansible }} codecov-token: ${{ secrets.CODECOV_TOKEN }} integration-continue-on-error: 'false' From 9e4b6c197d26f36785f2297d7b10568fa6173f81 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 14 Feb 2025 23:26:11 +0100 Subject: [PATCH 309/365] Remove outdated comments. --- .github/workflows/ansible-test.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index fa0a9cb..4835b43 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -31,11 +31,6 @@ jobs: - stable-2.17 - stable-2.18 - devel - # Ansible-test on various stable branches does not yet work well with cgroups v2. - # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 - # image for these stable branches. The list of branches where this is necessary will - # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 - # for the latest list. runs-on: ubuntu-latest steps: - name: Perform sanity testing @@ -50,11 +45,6 @@ jobs: git+https://github.com/ansible-collections/ansible.netcommon.git,main units: - # Ansible-test on various stable branches does not yet work well with cgroups v2. - # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 - # image for these stable branches. The list of branches where this is necessary will - # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 - # for the latest list. runs-on: ubuntu-latest name: Units (Ⓐ${{ matrix.ansible }}) strategy: @@ -82,11 +72,6 @@ jobs: git+https://github.com/ansible-collections/ansible.netcommon.git,main integration: - # Ansible-test on various stable branches does not yet work well with cgroups v2. - # Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04 - # image for these stable branches. The list of branches where this is necessary will - # shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28 - # for the latest list. runs-on: ubuntu-latest name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) strategy: From e302fed6cf1fda0f5e64f1af7113378fae69963f Mon Sep 17 00:00:00 2001 From: Tim de Boer Date: Tue, 18 Feb 2025 20:25:40 +0000 Subject: [PATCH 310/365] Added support for 'ip dns forwarders' (#343) --- .../fragments/343-add-ip-dns-forwarders.yml | 2 ++ plugins/module_utils/_api_data.py | 16 ++++++++++++++++ plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 20 insertions(+) create mode 100644 changelogs/fragments/343-add-ip-dns-forwarders.yml diff --git a/changelogs/fragments/343-add-ip-dns-forwarders.yml b/changelogs/fragments/343-add-ip-dns-forwarders.yml new file mode 100644 index 0000000..cd0a500 --- /dev/null +++ b/changelogs/fragments/343-add-ip-dns-forwarders.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add support for the ``ip dns forwarders`` path implemented by RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/343). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ce5c555..d1e2bbb 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2997,6 +2997,22 @@ PATHS = { )), ], ), + ('ip', 'dns', 'forwarders'): APIData( + versioned=[ + ('7.17', '>=', VersionedAPIData( + fully_understood=True, + required_one_of=[['dns-servers', 'doh-servers']], + fields={ + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'dns-servers': KeyInfo(default=''), + 'doh-servers': KeyInfo(default=''), + 'name': KeyInfo(required=True), + 'verify-doh-cert': KeyInfo(default=True), + }, + )), + ], + ), ('ip', 'dns', 'static'): APIData( unversioned=VersionedAPIData( fully_understood=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 346a317..b94e987 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -136,6 +136,7 @@ options: - ip dhcp-server option sets - ip dns - ip dns adlist + - ip dns forwarders - ip dns static - ip firewall address-list - ip firewall connection tracking diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index ef50293..1fb4dae 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -147,6 +147,7 @@ options: - ip dhcp-server option sets - ip dns - ip dns adlist + - ip dns forwarders - ip dns static - ip firewall address-list - ip firewall connection tracking From 3ba33ccd99f4d3cb13a7ce443ddb5f7e3235b940 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 24 Feb 2025 06:16:06 +0100 Subject: [PATCH 311/365] Remove primary key. (#345) --- changelogs/fragments/345-interface-wifi-provisioning.yml | 4 ++++ plugins/module_utils/_api_data.py | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/345-interface-wifi-provisioning.yml diff --git a/changelogs/fragments/345-interface-wifi-provisioning.yml b/changelogs/fragments/345-interface-wifi-provisioning.yml new file mode 100644 index 0000000..595b7f5 --- /dev/null +++ b/changelogs/fragments/345-interface-wifi-provisioning.yml @@ -0,0 +1,4 @@ +bugfixes: + - "api_info, api_modify - remove the primary key ``action`` from the ``interface wifi provisioning`` path, + since RouterOS also allows to create completely duplicate entries + (https://github.com/ansible-collections/community.routeros/issues/344, https://github.com/ansible-collections/community.routeros/pull/345)." diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index d1e2bbb..5ff335e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2037,7 +2037,6 @@ PATHS = { versioned=[ ('7.13', '>=', VersionedAPIData( fully_understood=True, - primary_keys=('action', ), fields={ 'action': KeyInfo(default='none'), 'address-ranges': KeyInfo(can_disable=True), From f54244b7d0b35dcb80f8f23fcf244ef62d53dfe9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 24 Feb 2025 06:08:45 +0100 Subject: [PATCH 312/365] Prepare 3.4.0. --- changelogs/fragments/3.4.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.4.0.yml diff --git a/changelogs/fragments/3.4.0.yml b/changelogs/fragments/3.4.0.yml new file mode 100644 index 0000000..80287c3 --- /dev/null +++ b/changelogs/fragments/3.4.0.yml @@ -0,0 +1 @@ +release_summary: Feature and bugfix release. diff --git a/galaxy.yml b/galaxy.yml index f127f37..704ec35 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.3.0 +version: 3.4.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From ffc928242b9c1e40bb828c51dfde0523cb997dd1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 24 Feb 2025 06:33:52 +0100 Subject: [PATCH 313/365] Release 3.4.0. --- CHANGELOG.md | 376 +++++++++--------- CHANGELOG.rst | 18 + changelogs/changelog.yaml | 16 + changelogs/fragments/3.4.0.yml | 1 - .../fragments/343-add-ip-dns-forwarders.yml | 2 - .../345-interface-wifi-provisioning.yml | 4 - 6 files changed, 233 insertions(+), 184 deletions(-) delete mode 100644 changelogs/fragments/3.4.0.yml delete mode 100644 changelogs/fragments/343-add-ip-dns-forwarders.yml delete mode 100644 changelogs/fragments/345-interface-wifi-provisioning.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 3458fc3..3ce4976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,149 +2,171 @@ **Topics** -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.0\.0 +- v3\.1\.0 - Release Summary + - Minor Changes + - Bugfixes +- v3\.0\.0 + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes - - Deprecated Features - - Bugfixes -- v2\.17\.0 +- v2\.18\.0 - Release Summary - Minor Changes -- v2\.16\.0 + - Deprecated Features + - Bugfixes +- v2\.17\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - Minor Changes - Bugfixes - - Known Issues -- v2\.3\.1 +- v2\.4\.0 - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - Minor Changes - Bugfixes -- v2\.2\.1 + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary - Bugfixes - - New Modules -- v2\.1\.0 +- v2\.2\.0 - Release Summary - Minor Changes - Bugfixes - - New Modules -- v2\.0\.0 + - New Modules +- v2\.1\.0 - Release Summary - Minor Changes - - Breaking Changes / Porting Guide - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 - - Release Summary - Bugfixes -- v1\.0\.0 +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary - - Minor Changes + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes - -## v3\.3\.0 + +## v3\.4\.0 ### Release Summary -Feature release\. +Feature and bugfix release\. ### Minor Changes +* api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. + + +### Bugfixes + +* api\_info\, api\_modify \- remove the primary key action from the interface wifi provisioning path\, since RouterOS also allows to create completely duplicate entries \([https\://github\.com/ansible\-collections/community\.routeros/issues/344](https\://github\.com/ansible\-collections/community\.routeros/issues/344)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/345](https\://github\.com/ansible\-collections/community\.routeros/pull/345)\)\. + + +## v3\.3\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. * api\_info\, api\_modify \- add the interface 6to4 path\. Used to manage IPv6 tunnels via tunnel\-brokers like HE\, where native IPv6 is not provided \([https\://github\.com/ansible\-collections/community\.routeros/pull/342](https\://github\.com/ansible\-collections/community\.routeros/pull/342)\)\. * api\_info\, api\_modify \- add the interface wireless access\-list and interface wireless connect\-list paths \([https\://github\.com/ansible\-collections/community\.routeros/issues/284](https\://github\.com/ansible\-collections/community\.routeros/issues/284)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/340](https\://github\.com/ansible\-collections/community\.routeros/pull/340)\)\. @@ -153,12 +175,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -166,17 +188,17 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. - + ### Bugfixes * api\_info\, api\_modify \- fields log and log\-prefix in paths ip firewall filter\, ip firewall mangle\, ip firewall nat\, ip firewall raw now have the correct default values \([https\://github\.com/ansible\-collections/community\.routeros/pull/324](https\://github\.com/ansible\-collections/community\.routeros/pull/324)\)\. @@ -184,7 +206,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -202,12 +224,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -218,12 +240,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -235,12 +257,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -256,7 +278,7 @@ Feature release\. * The collection deprecates support for all Ansible/ansible\-base/ansible\-core versions that are currently End of Life\, [according to the ansible\-core support matrix](https\://docs\.ansible\.com/ansible\-core/devel/reference\_appendices/release\_and\_maintenance\.html\#ansible\-core\-support\-matrix)\. This means that the next major release of the collection will no longer support Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. - + ### Bugfixes * api\_modify\, api\_info \- change the default of ingress\-filtering in paths interface bridge and interface bridge port back to false for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -264,21 +286,6 @@ Feature release\. ## v2\.17\.0 - -### Release Summary - -Feature release\. - - -### Minor Changes - -* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. -* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. -* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - - -## v2\.16\.0 - ### Release Summary @@ -287,11 +294,12 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. -* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. +* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. +* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. +* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -301,6 +309,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -315,12 +337,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -330,18 +352,18 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + ### Bugfixes * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. @@ -349,12 +371,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -368,12 +390,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -388,12 +410,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -417,7 +439,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -425,18 +447,18 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -444,7 +466,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -465,19 +487,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -486,35 +495,23 @@ Bugfix release\. ### Bugfixes -* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - -## v2\.8\.0 + +## v2\.8\.1 ### Release Summary -Bugfix and feature release\. - - -### Minor Changes - -* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. -* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. -* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. -* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. +Bugfix release\. ### Bugfixes -* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. - -## v2\.7\.0 + +## v2\.8\.0 ### Release Summary @@ -524,28 +521,53 @@ Bugfix and feature release\. ### Minor Changes -* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. ### Bugfixes +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -554,17 +576,17 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -572,12 +594,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -598,7 +620,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -616,7 +638,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -629,19 +651,19 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -649,12 +671,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -663,17 +685,17 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -687,12 +709,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -701,7 +723,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -716,12 +738,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -735,7 +757,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -757,12 +779,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -770,7 +792,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -778,12 +800,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -792,12 +814,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -805,12 +827,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -818,12 +840,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -831,12 +853,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8b57038..34a847d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,24 @@ Community RouterOS Release Notes .. contents:: Topics +v3.4.0 +====== + +Release Summary +--------------- + +Feature and bugfix release. + +Minor Changes +------------- + +- api_info, api_modify - add support for the ``ip dns forwarders`` path implemented by RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/343). + +Bugfixes +-------- + +- api_info, api_modify - remove the primary key ``action`` from the ``interface wifi provisioning`` path, since RouterOS also allows to create completely duplicate entries (https://github.com/ansible-collections/community.routeros/issues/344, https://github.com/ansible-collections/community.routeros/pull/345). + v3.3.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index a4fa82f..d76afb0 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -859,3 +859,19 @@ releases: - 341-add-dhcpv6-client-use-interface-duid.yml - 342-add-interface-6to4.yml release_date: '2025-01-27' + 3.4.0: + changes: + bugfixes: + - api_info, api_modify - remove the primary key ``action`` from the ``interface + wifi provisioning`` path, since RouterOS also allows to create completely + duplicate entries (https://github.com/ansible-collections/community.routeros/issues/344, + https://github.com/ansible-collections/community.routeros/pull/345). + minor_changes: + - api_info, api_modify - add support for the ``ip dns forwarders`` path implemented + by RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/343). + release_summary: Feature and bugfix release. + fragments: + - 3.4.0.yml + - 343-add-ip-dns-forwarders.yml + - 345-interface-wifi-provisioning.yml + release_date: '2025-02-24' diff --git a/changelogs/fragments/3.4.0.yml b/changelogs/fragments/3.4.0.yml deleted file mode 100644 index 80287c3..0000000 --- a/changelogs/fragments/3.4.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature and bugfix release. diff --git a/changelogs/fragments/343-add-ip-dns-forwarders.yml b/changelogs/fragments/343-add-ip-dns-forwarders.yml deleted file mode 100644 index cd0a500..0000000 --- a/changelogs/fragments/343-add-ip-dns-forwarders.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add support for the ``ip dns forwarders`` path implemented by RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/343). diff --git a/changelogs/fragments/345-interface-wifi-provisioning.yml b/changelogs/fragments/345-interface-wifi-provisioning.yml deleted file mode 100644 index 595b7f5..0000000 --- a/changelogs/fragments/345-interface-wifi-provisioning.yml +++ /dev/null @@ -1,4 +0,0 @@ -bugfixes: - - "api_info, api_modify - remove the primary key ``action`` from the ``interface wifi provisioning`` path, - since RouterOS also allows to create completely duplicate entries - (https://github.com/ansible-collections/community.routeros/issues/344, https://github.com/ansible-collections/community.routeros/pull/345)." From 6aaead1d4a6aee4a64cba06647d3e2e3cb012783 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 3 Mar 2025 19:00:16 +0100 Subject: [PATCH 314/365] Group CI updates. --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2f4ff90..f71b322 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: directory: "/" schedule: interval: "weekly" + groups: + ci: + patterns: + - "*" From be9a7ed3ad9db5d8e83f768b8cd600d2af5347f7 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 7 Mar 2025 20:45:39 +0100 Subject: [PATCH 315/365] Improve tests (#348) * Simplify filter error tests. * Convert set_module_args to context manager. --- .../targets/filter_quoting/tasks/main.yml | 2 +- tests/unit/plugins/modules/test_api.py | 76 ++++---- tests/unit/plugins/modules/test_api_facts.py | 12 +- .../modules/test_api_find_and_modify.py | 68 +++---- tests/unit/plugins/modules/test_api_info.py | 72 ++++---- tests/unit/plugins/modules/test_api_modify.py | 172 +++++++++--------- tests/unit/plugins/modules/test_command.py | 36 ++-- tests/unit/plugins/modules/test_facts.py | 20 +- tests/unit/plugins/modules/utils.py | 7 +- 9 files changed, 234 insertions(+), 231 deletions(-) diff --git a/tests/integration/targets/filter_quoting/tasks/main.yml b/tests/integration/targets/filter_quoting/tasks/main.yml index e7a2d29..c80af59 100644 --- a/tests/integration/targets/filter_quoting/tasks/main.yml +++ b/tests/integration/targets/filter_quoting/tasks/main.yml @@ -22,7 +22,7 @@ assert: that: - >- - result.msg == "Unexpected end of string during escaped parameter" + "Unexpected end of string during escaped parameter" in result.msg - name: "Test quote_argument filter" assert: diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index 4cfdeef..5df8430 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -34,8 +34,8 @@ class TestRouterosApiModule(ModuleTestCase): def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: - set_module_args({}) - self.module.main() + with set_module_args({}): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -43,8 +43,8 @@ class TestRouterosApiModule(ModuleTestCase): @patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.path) def test_api_path(self): with self.assertRaises(AnsibleExitJson) as exc: - set_module_args(self.config_module_args.copy()) - self.module.main() + with set_module_args(self.config_module_args.copy()): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -54,8 +54,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['add'] = "name=unit_test_brige" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -65,8 +65,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: module_args = self.config_module_args.copy() module_args['add'] = "name=unit_test_brige_exist" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -77,8 +77,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['remove'] = "*A1" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -88,8 +88,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: module_args = self.config_module_args.copy() module_args['remove'] = "*A2" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -100,8 +100,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['cmd'] = "add name=unit_test_brige_arbitrary" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -111,8 +111,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: module_args = self.config_module_args.copy() module_args['cmd'] = "add NONE_EXIST=unit_test_brige_arbitrary" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -123,8 +123,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['update'] = ".id=*A1 name=unit_test_brige" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -134,8 +134,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: module_args = self.config_module_args.copy() module_args['update'] = ".id=*A2 name=unit_test_brige" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -146,8 +146,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['query'] = ".id name" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -162,8 +162,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['query'] = ".id other" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -174,8 +174,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['query'] = ".id name WHERE name == dummy_bridge_A2" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -188,8 +188,8 @@ class TestRouterosApiModule(ModuleTestCase): with self.assertRaises(AnsibleExitJson) as exc: module_args = self.config_module_args.copy() module_args['query'] = ".id name WHERE name != dummy_bridge_A2" - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -204,8 +204,8 @@ class TestRouterosApiModule(ModuleTestCase): module_args['extended_query'] = { 'attributes': ['.id', 'name'], } - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -222,8 +222,8 @@ class TestRouterosApiModule(ModuleTestCase): module_args['extended_query'] = { 'attributes': ['.id', 'other'], } - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -243,8 +243,8 @@ class TestRouterosApiModule(ModuleTestCase): }, ], } - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -266,8 +266,8 @@ class TestRouterosApiModule(ModuleTestCase): }, ], } - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -298,8 +298,8 @@ class TestRouterosApiModule(ModuleTestCase): }, ], } - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py index 64985f8..f9c76be 100644 --- a/tests/unit/plugins/modules/test_api_facts.py +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -437,8 +437,8 @@ class TestRouterosApiFactsModule(ModuleTestCase): def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: - set_module_args({}) - self.module.main() + with set_module_args({}): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -447,8 +447,8 @@ class TestRouterosApiFactsModule(ModuleTestCase): with self.assertRaises(AnsibleFailJson) as exc: module_args = self.config_module_args.copy() module_args['gather_subset'] = ['!foobar'] - set_module_args(module_args) - self.module.main() + with set_module_args(module_args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -456,8 +456,8 @@ class TestRouterosApiFactsModule(ModuleTestCase): def test_full_run(self): with self.assertRaises(AnsibleExitJson) as exc: - set_module_args(self.config_module_args.copy()) - self.module.main() + with set_module_args(self.config_module_args.copy()): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index e6eb00b..b25fbce 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -117,8 +117,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: - set_module_args({}) - self.module.main() + with set_module_args({}): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -136,8 +136,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'bar', }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -155,8 +155,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': 'bar', }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -173,8 +173,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): '!comment': None, }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -190,8 +190,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): '!comment': 'gone', }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -212,8 +212,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): }, 'require_matches_min': 10, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -234,8 +234,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): }, 'require_matches_min': 10, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -256,8 +256,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): }, 'require_matches_max': 1, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -277,8 +277,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'name': 'bam', }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -303,8 +303,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'require_matches_min': 2, 'allow_no_matches': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -325,8 +325,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'values': { }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -349,8 +349,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': None, }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -374,8 +374,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): }, '_ansible_diff': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -450,8 +450,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': None, }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -502,8 +502,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): 'comment': '', }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -553,8 +553,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): '!comment': None, }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -606,8 +606,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): '!connection-state': None, }, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 1c9d014..d20aa11 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -41,8 +41,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: - set_module_args({}) - self.module.main() + with set_module_args({}): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -53,8 +53,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): args.update({ 'path': 'something invalid' }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -68,8 +68,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): args.update({ 'path': 'ip dns static' }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -93,8 +93,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): args.update({ 'path': 'caps-man aaa', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -122,8 +122,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'caps-man aaa', 'hide_defaults': False, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -155,8 +155,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'caps-man aaa', 'unfiltered': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -189,8 +189,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'ip firewall filter', 'handle_disabled': 'exclamation', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -278,8 +278,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'ip firewall filter', 'handle_disabled': 'null-value', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -367,8 +367,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'ip firewall filter', 'handle_disabled': 'omit', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -402,8 +402,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'handle_disabled': 'omit', 'include_dynamic': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -460,8 +460,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'interface list', 'handle_disabled': 'omit', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -513,8 +513,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'handle_disabled': 'omit', 'include_builtin': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -605,8 +605,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'path': 'ip dhcp-server lease', 'handle_disabled': 'omit', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -688,8 +688,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): args.update({ 'path': 'interface gre', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -776,8 +776,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'handle_disabled': 'omit', 'hide_defaults': False, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -847,8 +847,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'handle_disabled': 'omit', 'restrict': [], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -899,8 +899,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): 'values': ['forward'], }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -970,8 +970,8 @@ class TestRouterosApiInfoModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index f4aa777..20e29e1 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -318,8 +318,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): def test_module_fail_when_required_args_missing(self): with self.assertRaises(AnsibleFailJson) as exc: - set_module_args({}) - self.module.main() + with set_module_args({}): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -331,8 +331,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'path': 'something invalid', 'data': [], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -348,8 +348,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'foo': 'bar', }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -366,8 +366,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): '!comment': None, }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -383,8 +383,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): '!disabled': None, }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -400,8 +400,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): '!comment': 'foo', }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -416,8 +416,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'name': None, }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -432,8 +432,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'interface': 'eth0', }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -448,8 +448,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -466,8 +466,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'address': '192.168.88.1', }], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['failed'], True) @@ -498,8 +498,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -533,8 +533,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -556,8 +556,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -591,8 +591,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -656,8 +656,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -722,8 +722,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): ], '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -785,8 +785,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -844,8 +844,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -903,8 +903,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -963,8 +963,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1017,8 +1017,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1077,8 +1077,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1128,8 +1128,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1164,8 +1164,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1212,8 +1212,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1285,8 +1285,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'ensure_order': True, '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1340,8 +1340,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1363,8 +1363,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): ], 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1386,8 +1386,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1426,8 +1426,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): ], '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1466,8 +1466,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): ], 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1507,8 +1507,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1551,8 +1551,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): }, ], }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1587,8 +1587,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1621,8 +1621,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'handle_entries_content': 'remove', }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1676,8 +1676,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1729,8 +1729,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1785,8 +1785,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'ensure_order': True, '_ansible_check_mode': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1847,8 +1847,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1879,8 +1879,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -1911,8 +1911,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_entries_content': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], True) @@ -1969,8 +1969,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) @@ -2005,8 +2005,8 @@ class TestRouterosApiModifyModule(ModuleTestCase): 'handle_absent_entries': 'remove', 'ensure_order': True, }) - set_module_args(args) - self.module.main() + with set_module_args(args): + self.module.main() result = exc.exception.args[0] self.assertEqual(result['changed'], False) diff --git a/tests/unit/plugins/modules/test_command.py b/tests/unit/plugins/modules/test_command.py index 3fc5865..72fbfd6 100644 --- a/tests/unit/plugins/modules/test_command.py +++ b/tests/unit/plugins/modules/test_command.py @@ -47,54 +47,54 @@ class TestRouterosCommandModule(TestRouterosModule): self.run_commands.side_effect = load_from_file def test_command_simple(self): - set_module_args(dict(commands=['/system resource print'])) - result = self.execute_module(changed=True) + with set_module_args(dict(commands=['/system resource print'])): + result = self.execute_module(changed=True) self.assertEqual(len(result['stdout']), 1) self.assertTrue('platform: "MikroTik"' in result['stdout'][0]) def test_command_multiple(self): - set_module_args(dict(commands=['/system resource print', '/system resource print'])) - result = self.execute_module(changed=True) + with set_module_args(dict(commands=['/system resource print', '/system resource print'])): + result = self.execute_module(changed=True) self.assertEqual(len(result['stdout']), 2) self.assertTrue('platform: "MikroTik"' in result['stdout'][0]) def test_command_wait_for(self): wait_for = 'result[0] contains "MikroTik"' - set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)) - self.execute_module(changed=True) + with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)): + self.execute_module(changed=True) def test_command_wait_for_fails(self): wait_for = 'result[0] contains "test string"' - set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)) - self.execute_module(failed=True) + with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)): + self.execute_module(failed=True) self.assertEqual(self.run_commands.call_count, 10) def test_command_retries(self): wait_for = 'result[0] contains "test string"' - set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, retries=2)) - self.execute_module(failed=True) + with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, retries=2)): + self.execute_module(failed=True) self.assertEqual(self.run_commands.call_count, 2) def test_command_match_any(self): wait_for = ['result[0] contains "MikroTik"', 'result[0] contains "test string"'] - set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='any')) - self.execute_module(changed=True) + with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='any')): + self.execute_module(changed=True) def test_command_match_all(self): wait_for = ['result[0] contains "MikroTik"', 'result[0] contains "RB1100"'] - set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='all')) - self.execute_module(changed=True) + with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='all')): + self.execute_module(changed=True) def test_command_match_all_failure(self): wait_for = ['result[0] contains "MikroTik"', 'result[0] contains "test string"'] commands = ['/system resource print', '/system resource print'] - set_module_args(dict(commands=commands, wait_for=wait_for, match='all')) - self.execute_module(failed=True) + with set_module_args(dict(commands=commands, wait_for=wait_for, match='all')): + self.execute_module(failed=True) def test_command_wait_for_2(self): wait_for = 'result[0] contains "wireless"' - set_module_args(dict(commands=['/system package print'], wait_for=wait_for)) - self.execute_module(changed=True) + with set_module_args(dict(commands=['/system package print'], wait_for=wait_for)): + self.execute_module(changed=True) diff --git a/tests/unit/plugins/modules/test_facts.py b/tests/unit/plugins/modules/test_facts.py index 322fdda..a7e2c8b 100644 --- a/tests/unit/plugins/modules/test_facts.py +++ b/tests/unit/plugins/modules/test_facts.py @@ -39,8 +39,8 @@ class TestRouterosFactsModule(TestRouterosModule): self.run_commands.side_effect = load_from_file def test_facts_default(self): - set_module_args(dict(gather_subset='default')) - result = self.execute_module() + with set_module_args(dict(gather_subset='default')): + result = self.execute_module() self.assertEqual( result['ansible_facts']['ansible_net_hostname'], 'MikroTik' ) @@ -61,8 +61,8 @@ class TestRouterosFactsModule(TestRouterosModule): ) def test_facts_hardware(self): - set_module_args(dict(gather_subset='hardware')) - result = self.execute_module() + with set_module_args(dict(gather_subset='hardware')): + result = self.execute_module() self.assertEqual( result['ansible_facts']['ansible_net_spacefree_mb'], 64921.6 ) @@ -77,8 +77,8 @@ class TestRouterosFactsModule(TestRouterosModule): ) def test_facts_config(self): - set_module_args(dict(gather_subset='config')) - result = self.execute_module() + with set_module_args(dict(gather_subset='config')): + result = self.execute_module() self.assertIsInstance( result['ansible_facts']['ansible_net_config'], str ) @@ -88,8 +88,8 @@ class TestRouterosFactsModule(TestRouterosModule): ) def test_facts_interfaces(self): - set_module_args(dict(gather_subset='interfaces')) - result = self.execute_module() + with set_module_args(dict(gather_subset='interfaces')): + result = self.execute_module() self.assertIn( result['ansible_facts']['ansible_net_all_ipv4_addresses'][0], ['10.37.129.3', '10.37.0.0', '192.168.88.1'] ) @@ -118,8 +118,8 @@ class TestRouterosFactsModule(TestRouterosModule): self.assertEqual(result, None) def test_facts_routing(self): - set_module_args(dict(gather_subset='routing')) - result = self.execute_module() + with set_module_args(dict(gather_subset='routing')): + result = self.execute_module() self.assertIn( result['ansible_facts']['ansible_net_bgp_peer']['iBGP_BRAS.TYRMA']['name'], ['iBGP_BRAS.TYRMA'] ) diff --git a/tests/unit/plugins/modules/utils.py b/tests/unit/plugins/modules/utils.py index 419eef1..0926190 100644 --- a/tests/unit/plugins/modules/utils.py +++ b/tests/unit/plugins/modules/utils.py @@ -5,6 +5,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +import contextlib as _contextlib import json from ansible_collections.community.routeros.tests.unit.compat import unittest @@ -13,14 +14,16 @@ from ansible.module_utils import basic from ansible.module_utils.common.text.converters import to_bytes +@_contextlib.contextmanager 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) + serialized_args = to_bytes(json.dumps({'ANSIBLE_MODULE_ARGS': args})) + with patch.object(basic, '_ANSIBLE_ARGS', serialized_args): + yield class AnsibleExitJson(Exception): From ab446b44492f7c6b765e77240bff468f27772092 Mon Sep 17 00:00:00 2001 From: hansmi Date: Wed, 12 Mar 2025 20:06:39 +0100 Subject: [PATCH 316/365] Fix typo in "API" (#351) --- plugins/modules/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 7d90045..4e42912 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -67,7 +67,7 @@ options: type: str query: description: - - Query given path for selected query attributes from RouterOS aip. + - Query given path for selected query attributes from RouterOS API. - WHERE is key word which extend query. WHERE format is key operator value - with spaces. - WHERE valid operators are V(==) or V(eq), V(!=) or V(not), V(>) or V(more), V(<) or V(less). - Example path V(ip address) and query V(.id address) will return only C(.id) and C(address) for all items in V(ip address) From 30a79061f388ed30664216250f58213bc7be8bab Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 12 Mar 2025 21:34:12 +0100 Subject: [PATCH 317/365] Use shared unit test utils from community.internal_test_tools (#353) * Use shared unit test utils from community.internal_test_tools. * Make sure community.internal_test_tools is installed in CI. --- .github/workflows/ansible-test.yml | 3 + tests/sanity/ignore-2.17.txt | 1 - tests/sanity/ignore-2.18.txt | 1 - tests/sanity/ignore-2.19.txt | 1 - tests/unit/compat/__init__.py | 0 tests/unit/compat/builtins.py | 20 ---- tests/unit/compat/mock.py | 109 ------------------ tests/unit/compat/unittest.py | 25 ---- tests/unit/plugins/modules/routeros_module.py | 2 +- tests/unit/plugins/modules/test_api.py | 5 +- tests/unit/plugins/modules/test_api_facts.py | 5 +- .../modules/test_api_find_and_modify.py | 5 +- tests/unit/plugins/modules/test_api_info.py | 5 +- tests/unit/plugins/modules/test_api_modify.py | 5 +- tests/unit/plugins/modules/test_command.py | 5 +- tests/unit/plugins/modules/test_facts.py | 5 +- tests/unit/plugins/modules/utils.py | 57 --------- 17 files changed, 25 insertions(+), 229 deletions(-) delete mode 100644 tests/unit/compat/__init__.py delete mode 100644 tests/unit/compat/builtins.py delete mode 100644 tests/unit/compat/mock.py delete mode 100644 tests/unit/compat/unittest.py delete mode 100644 tests/unit/plugins/modules/utils.py diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml index 4835b43..45ca774 100644 --- a/.github/workflows/ansible-test.yml +++ b/.github/workflows/ansible-test.yml @@ -43,6 +43,7 @@ jobs: test-deps: >- git+https://github.com/ansible-collections/ansible.utils.git,main git+https://github.com/ansible-collections/ansible.netcommon.git,main + git+https://github.com/ansible-collections/community.internal_test_tools.git,main units: runs-on: ubuntu-latest @@ -70,6 +71,7 @@ jobs: test-deps: >- git+https://github.com/ansible-collections/ansible.utils.git,main git+https://github.com/ansible-collections/ansible.netcommon.git,main + git+https://github.com/ansible-collections/community.internal_test_tools.git,main integration: runs-on: ubuntu-latest @@ -118,5 +120,6 @@ jobs: test-deps: >- git+https://github.com/ansible-collections/ansible.utils.git,main git+https://github.com/ansible-collections/ansible.netcommon.git,main + git+https://github.com/ansible-collections/community.internal_test_tools.git,main target-python-version: ${{ matrix.python }} testing-type: integration diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt index 0a5234b..ce635c3 100644 --- a/tests/sanity/ignore-2.17.txt +++ b/tests/sanity/ignore-2.17.txt @@ -1,2 +1 @@ update-docs.py shebang -tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 diff --git a/tests/sanity/ignore-2.18.txt b/tests/sanity/ignore-2.18.txt index 0a5234b..ce635c3 100644 --- a/tests/sanity/ignore-2.18.txt +++ b/tests/sanity/ignore-2.18.txt @@ -1,2 +1 @@ update-docs.py shebang -tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 diff --git a/tests/sanity/ignore-2.19.txt b/tests/sanity/ignore-2.19.txt index 0a5234b..ce635c3 100644 --- a/tests/sanity/ignore-2.19.txt +++ b/tests/sanity/ignore-2.19.txt @@ -1,2 +1 @@ update-docs.py shebang -tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2 diff --git a/tests/unit/compat/__init__.py b/tests/unit/compat/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/unit/compat/builtins.py b/tests/unit/compat/builtins.py deleted file mode 100644 index d548601..0000000 --- a/tests/unit/compat/builtins.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2014, Toshio Kuratomi -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -# 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__ # noqa: F401, pylint: disable=unused-import -except ImportError: - BUILTINS = 'builtins' -else: - BUILTINS = '__builtin__' diff --git a/tests/unit/compat/mock.py b/tests/unit/compat/mock.py deleted file mode 100644 index bdbea94..0000000 --- a/tests/unit/compat/mock.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) 2014, Toshio Kuratomi -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -# 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 * # noqa: F401, pylint: disable=unused-import -except ImportError: - # Python 2 - # pylint: disable=wildcard-import,unused-wildcard-import - try: - from mock import * # noqa: F401, pylint: disable=unused-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 deleted file mode 100644 index d50bab8..0000000 --- a/tests/unit/compat/unittest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2014, Toshio Kuratomi -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -# 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 * # noqa: F401, pylint: disable=unused-import - except ImportError: - print('You need unittest2 installed on python2.6.x to run tests') -else: - from unittest import * # noqa: F401, pylint: disable=unused-import diff --git a/tests/unit/plugins/modules/routeros_module.py b/tests/unit/plugins/modules/routeros_module.py index 0ec44f7..4786da6 100644 --- a/tests/unit/plugins/modules/routeros_module.py +++ b/tests/unit/plugins/modules/routeros_module.py @@ -9,7 +9,7 @@ __metaclass__ = type import os import json -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures') diff --git a/tests/unit/plugins/modules/test_api.py b/tests/unit/plugins/modules/test_api.py index 5df8430..9a03825 100644 --- a/tests/unit/plugins/modules/test_api.py +++ b/tests/unit/plugins/modules/test_api.py @@ -6,9 +6,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase + from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, Or, fake_ros_api -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api diff --git a/tests/unit/plugins/modules/test_api_facts.py b/tests/unit/plugins/modules/test_api_facts.py index f9c76be..7b019f9 100644 --- a/tests/unit/plugins/modules/test_api_facts.py +++ b/tests/unit/plugins/modules/test_api_facts.py @@ -6,9 +6,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase + from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import FakeLibRouterosError, Key, fake_ros_api -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_facts diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index b25fbce..fe5e180 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -6,11 +6,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase + from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, ) -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_find_and_modify diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index d20aa11..967a854 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -6,11 +6,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase + from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( FAKE_ROS_VERSION, FakeLibRouterosError, Key, fake_ros_api, ) -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_info diff --git a/tests/unit/plugins/modules/test_api_modify.py b/tests/unit/plugins/modules/test_api_modify.py index 20e29e1..6edc046 100644 --- a/tests/unit/plugins/modules/test_api_modify.py +++ b/tests/unit/plugins/modules/test_api_modify.py @@ -6,11 +6,12 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, MagicMock +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase + from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import ( FAKE_ROS_VERSION, FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path, ) -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args, AnsibleExitJson, AnsibleFailJson, ModuleTestCase from ansible_collections.community.routeros.plugins.modules import api_modify diff --git a/tests/unit/plugins/modules/test_command.py b/tests/unit/plugins/modules/test_command.py index 72fbfd6..06153f0 100644 --- a/tests/unit/plugins/modules/test_command.py +++ b/tests/unit/plugins/modules/test_command.py @@ -8,9 +8,10 @@ __metaclass__ = type import json -from ansible_collections.community.routeros.tests.unit.compat.mock import patch +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args + from ansible_collections.community.routeros.plugins.modules import command -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args from .routeros_module import TestRouterosModule, load_fixture diff --git a/tests/unit/plugins/modules/test_facts.py b/tests/unit/plugins/modules/test_facts.py index a7e2c8b..918f378 100644 --- a/tests/unit/plugins/modules/test_facts.py +++ b/tests/unit/plugins/modules/test_facts.py @@ -6,9 +6,10 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from ansible_collections.community.routeros.tests.unit.compat.mock import patch +from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch +from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import set_module_args + from ansible_collections.community.routeros.plugins.modules import facts -from ansible_collections.community.routeros.tests.unit.plugins.modules.utils import set_module_args from .routeros_module import TestRouterosModule, load_fixture diff --git a/tests/unit/plugins/modules/utils.py b/tests/unit/plugins/modules/utils.py deleted file mode 100644 index 0926190..0000000 --- a/tests/unit/plugins/modules/utils.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -import contextlib as _contextlib -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.common.text.converters import to_bytes - - -@_contextlib.contextmanager -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 - - serialized_args = to_bytes(json.dumps({'ANSIBLE_MODULE_ARGS': args})) - with patch.object(basic, '_ANSIBLE_ARGS', serialized_args): - yield - - -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) From 873699631723bd6875b9292da7db9e0ea8642be5 Mon Sep 17 00:00:00 2001 From: hansmi Date: Thu, 13 Mar 2025 07:08:14 +0100 Subject: [PATCH 318/365] Change default for ddns-enabled to "auto" for RouterOS 7.17 and newer (#350) From the RouterOS 7.17 changelog: > *) cloud - changed ddns-enabled setting from "no" to "auto" (service > is enabled when BTH is enabled); `no` is not supported anymore, only `yes` and `auto` are. --- changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml | 2 ++ plugins/module_utils/_api_data.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml diff --git a/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml b/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml new file mode 100644 index 0000000..6d9d443 --- /dev/null +++ b/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - change default for ``/ip/cloud/ddns-enabled`` for RouterOS 7.17 and newer from ``yes`` to ``auto`` (https://github.com/ansible-collections/community.routeros/pull/350). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 5ff335e..56e487a 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2777,8 +2777,11 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.17', '<')], 'ddns-enabled', KeyInfo(default=False)), + ([('7.17', '>=')], 'ddns-enabled', KeyInfo(default='auto')), + ], fields={ - 'ddns-enabled': KeyInfo(default=False), 'ddns-update-interval': KeyInfo(default='none'), 'update-time': KeyInfo(default=True), }, From 2b1be7f011c62519327368159ed1721832f479fd Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 21 Mar 2025 22:07:58 +0100 Subject: [PATCH 319/365] Prepare 3.5.0. --- changelogs/fragments/3.5.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.5.0.yml diff --git a/changelogs/fragments/3.5.0.yml b/changelogs/fragments/3.5.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.5.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index 704ec35..3557098 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.4.0 +version: 3.5.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 9d382a1b10672089dc5a8dd08dca4b7e4268dd10 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 22 Mar 2025 12:39:33 +0100 Subject: [PATCH 320/365] Release 3.5.0. --- CHANGELOG.md | 256 ++++++++++-------- CHANGELOG.rst | 13 + changelogs/changelog.yaml | 10 + changelogs/fragments/3.5.0.yml | 1 - .../350-ip-cloud-ddns-enabled-auto.yml | 2 - 5 files changed, 159 insertions(+), 123 deletions(-) delete mode 100644 changelogs/fragments/3.5.0.yml delete mode 100644 changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce4976..fd9b85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,153 +2,169 @@ **Topics** -- v3\.4\.0 +- v3\.5\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.4\.0 + +## v3\.5\.0 ### Release Summary -Feature and bugfix release\. +Feature release\. ### Minor Changes +* api\_info\, api\_modify \- change default for /ip/cloud/ddns\-enabled for RouterOS 7\.17 and newer from yes to auto \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\. + + +## v3\.4\.0 + + +### Release Summary + +Feature and bugfix release\. + + +### Minor Changes + * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. @@ -159,12 +175,12 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. @@ -175,12 +191,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -188,12 +204,12 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -206,7 +222,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -224,12 +240,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -240,12 +256,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -257,12 +273,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -286,12 +302,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -301,12 +317,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -315,12 +331,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -337,12 +353,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -352,12 +368,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -371,12 +387,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -390,12 +406,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -410,12 +426,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -447,12 +463,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -466,7 +482,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -487,7 +503,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -500,7 +516,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -513,12 +529,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -538,12 +554,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -556,12 +572,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -576,12 +592,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -594,12 +610,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -638,7 +654,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -651,12 +667,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -671,7 +687,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -685,12 +701,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -709,12 +725,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -738,12 +754,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -779,12 +795,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -800,12 +816,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -814,7 +830,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -827,7 +843,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -840,7 +856,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -853,12 +869,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 34a847d..6a82da8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,19 @@ Community RouterOS Release Notes .. contents:: Topics +v3.5.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - change default for ``/ip/cloud/ddns-enabled`` for RouterOS 7.17 and newer from ``yes`` to ``auto`` (https://github.com/ansible-collections/community.routeros/pull/350). + v3.4.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index d76afb0..ee957d5 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -875,3 +875,13 @@ releases: - 343-add-ip-dns-forwarders.yml - 345-interface-wifi-provisioning.yml release_date: '2025-02-24' + 3.5.0: + changes: + minor_changes: + - api_info, api_modify - change default for ``/ip/cloud/ddns-enabled`` for + RouterOS 7.17 and newer from ``yes`` to ``auto`` (https://github.com/ansible-collections/community.routeros/pull/350). + release_summary: Feature release. + fragments: + - 3.5.0.yml + - 350-ip-cloud-ddns-enabled-auto.yml + release_date: '2025-03-22' diff --git a/changelogs/fragments/3.5.0.yml b/changelogs/fragments/3.5.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.5.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml b/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml deleted file mode 100644 index 6d9d443..0000000 --- a/changelogs/fragments/350-ip-cloud-ddns-enabled-auto.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - change default for ``/ip/cloud/ddns-enabled`` for RouterOS 7.17 and newer from ``yes`` to ``auto`` (https://github.com/ansible-collections/community.routeros/pull/350). From a920caa16af3cc6822b73e356ba7ab7f8419e002 Mon Sep 17 00:00:00 2001 From: hansmi Date: Wed, 26 Mar 2025 06:51:10 +0100 Subject: [PATCH 321/365] Add "mdns-repeat-ifaces" field to "ip dns" (#358) RouterOS 7.16 introduced an mDNS proxy, configurable via `mdns-repeat-ifaces` under `/ip/dns`. --- changelogs/fragments/358-mdns-repeat-ifaces.yml | 2 ++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/358-mdns-repeat-ifaces.yml diff --git a/changelogs/fragments/358-mdns-repeat-ifaces.yml b/changelogs/fragments/358-mdns-repeat-ifaces.yml new file mode 100644 index 0000000..3cd6d62 --- /dev/null +++ b/changelogs/fragments/358-mdns-repeat-ifaces.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``mdns-repeat-ifaces`` to ``ip dns`` for RouterOS 7.16 and newer (https://github.com/ansible-collections/community.routeros/pull/358). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 56e487a..f239750 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2967,6 +2967,7 @@ PATHS = { ([('7.8', '>=')], 'doh-max-concurrent-queries', KeyInfo(default=50)), ([('7.8', '>=')], 'doh-max-server-connections', KeyInfo(default=5)), ([('7.8', '>=')], 'doh-timeout', KeyInfo(default='5s')), + ([('7.16', '>=')], 'mdns-repeat-ifaces', KeyInfo()), ], fields={ 'allow-remote-requests': KeyInfo(), From 3a34752296df4677ae48cd6e7c6d420803f1b599 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 29 Mar 2025 12:17:25 +0100 Subject: [PATCH 322/365] Migrate .reuse/dep5 to REUSE.toml. --- .reuse/dep5 | 5 ----- REUSE.toml | 11 +++++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 .reuse/dep5 create mode 100644 REUSE.toml diff --git a/.reuse/dep5 b/.reuse/dep5 deleted file mode 100644 index 0c3745e..0000000 --- a/.reuse/dep5 +++ /dev/null @@ -1,5 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ - -Files: changelogs/fragments/* -Copyright: Ansible Project -License: GPL-3.0-or-later diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000..ff95bb8 --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,11 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +version = 1 + +[[annotations]] +path = "changelogs/fragments/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "Ansible Project" +SPDX-License-Identifier = "GPL-3.0-or-later" From 9dba8082f9de797066fe68b404362adf3a73960e Mon Sep 17 00:00:00 2001 From: Tim de Boer Date: Thu, 10 Apr 2025 12:03:08 +0100 Subject: [PATCH 323/365] Field name change in 'routing bgp connection' (from 'address-families' to 'afi') (#360) * Field name change in 'routing bgp connection' (from 'address-families' to 'afi') * Field name change in 'routing bgp connection' (from 'address-families' to 'afi') --- changelogs/fragments/360-bgp-connection-afi.yml | 2 ++ plugins/module_utils/_api_data.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/360-bgp-connection-afi.yml diff --git a/changelogs/fragments/360-bgp-connection-afi.yml b/changelogs/fragments/360-bgp-connection-afi.yml new file mode 100644 index 0000000..13e89ea --- /dev/null +++ b/changelogs/fragments/360-bgp-connection-afi.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_modify, api_info - field name change in ``routing bgp connection`` path implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index f239750..10a6216 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4982,10 +4982,13 @@ PATHS = { ('routing', 'bgp', 'connection'): APIData( unversioned=VersionedAPIData( fully_understood=True, + versioned_fields=[ + ([('7.19', '<')], 'address-families', KeyInfo()), + ([('7.19', '>=')], 'afi', KeyInfo()), + ], fields={ 'as': KeyInfo(), 'add-path-out': KeyInfo(), - 'address-families': KeyInfo(), 'cisco-vpls-nlri-len-fmt': KeyInfo(), 'cluster-id': KeyInfo(), 'comment': KeyInfo(), From e286d768c0c83e01cb2fd87ec5e7e4a0c7d3d905 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 19 Apr 2025 13:07:53 +0200 Subject: [PATCH 324/365] Use antsibull-nox for CI. (#361) --- .github/workflows/ansible-test.yml | 125 ------------------ .github/workflows/extra-tests.yml | 52 -------- .github/workflows/import-galaxy.yml | 20 --- .github/workflows/{reuse.yml => nox.yml} | 28 ++-- README.md | 2 +- antsibull-nox.toml | 57 ++++++++ noxfile.py | 50 +++++++ tests/sanity/extra/action-group.json | 12 -- tests/sanity/extra/action-group.json.license | 3 - tests/sanity/extra/action-group.py | 119 ----------------- tests/sanity/extra/extra-docs.json | 13 -- tests/sanity/extra/extra-docs.json.license | 3 - tests/sanity/extra/extra-docs.py | 29 ---- tests/sanity/extra/licenses.json | 4 - tests/sanity/extra/licenses.json.license | 3 - tests/sanity/extra/licenses.py | 110 --------------- tests/sanity/extra/licenses.py.license | 3 - tests/sanity/extra/no-unwanted-files.json | 7 - .../extra/no-unwanted-files.json.license | 3 - tests/sanity/extra/no-unwanted-files.py | 58 -------- tests/sanity/extra/update-docs.json | 11 -- tests/sanity/extra/update-docs.json.license | 3 - tests/sanity/extra/update-docs.py | 21 --- tests/sanity/ignore-2.10.txt | 12 +- tests/sanity/ignore-2.11.txt | 12 +- tests/sanity/ignore-2.12.txt | 2 +- tests/sanity/ignore-2.13.txt | 2 +- tests/sanity/ignore-2.14.txt | 2 +- tests/sanity/ignore-2.15.txt | 2 +- tests/sanity/ignore-2.16.txt | 2 +- tests/sanity/ignore-2.17.txt | 2 +- tests/sanity/ignore-2.18.txt | 2 +- tests/sanity/ignore-2.19.txt | 2 +- tests/sanity/ignore-2.9.txt | 12 +- tests/unit/requirements.yml | 2 +- update-docs.py => tests/update-docs.py | 29 ++-- 36 files changed, 168 insertions(+), 651 deletions(-) delete mode 100644 .github/workflows/ansible-test.yml delete mode 100644 .github/workflows/extra-tests.yml delete mode 100644 .github/workflows/import-galaxy.yml rename .github/workflows/{reuse.yml => nox.yml} (50%) create mode 100644 antsibull-nox.toml create mode 100644 noxfile.py delete mode 100644 tests/sanity/extra/action-group.json delete mode 100644 tests/sanity/extra/action-group.json.license delete mode 100755 tests/sanity/extra/action-group.py delete mode 100644 tests/sanity/extra/extra-docs.json delete mode 100644 tests/sanity/extra/extra-docs.json.license delete mode 100755 tests/sanity/extra/extra-docs.py delete mode 100644 tests/sanity/extra/licenses.json delete mode 100644 tests/sanity/extra/licenses.json.license delete mode 100755 tests/sanity/extra/licenses.py delete mode 100644 tests/sanity/extra/licenses.py.license delete mode 100644 tests/sanity/extra/no-unwanted-files.json delete mode 100644 tests/sanity/extra/no-unwanted-files.json.license delete mode 100755 tests/sanity/extra/no-unwanted-files.py delete mode 100644 tests/sanity/extra/update-docs.json delete mode 100644 tests/sanity/extra/update-docs.json.license delete mode 100644 tests/sanity/extra/update-docs.py rename update-docs.py => tests/update-docs.py (62%) mode change 100755 => 100644 diff --git a/.github/workflows/ansible-test.yml b/.github/workflows/ansible-test.yml deleted file mode 100644 index 45ca774..0000000 --- a/.github/workflows/ansible-test.yml +++ /dev/null @@ -1,125 +0,0 @@ ---- -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see -# https://github.com/marketplace/actions/ansible-test - -name: CI -on: - # Run CI against all pushes (direct commits, also merged PRs), Pull Requests - push: - branches: - - main - - stable-* - pull_request: - # Run CI once per day (at 05:15 UTC) - schedule: - - cron: '15 5 * * *' - -jobs: - sanity: - name: Sanity (Ⓐ${{ matrix.ansible }}) - strategy: - matrix: - 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.15 - - stable-2.16 - - stable-2.17 - - stable-2.18 - - devel - runs-on: ubuntu-latest - steps: - - name: Perform sanity testing - uses: felixfontein/ansible-test-gh-action@main - with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} - ansible-core-version: ${{ matrix.ansible }} - codecov-token: ${{ secrets.CODECOV_TOKEN }} - testing-type: sanity - test-deps: >- - git+https://github.com/ansible-collections/ansible.utils.git,main - git+https://github.com/ansible-collections/ansible.netcommon.git,main - git+https://github.com/ansible-collections/community.internal_test_tools.git,main - - units: - runs-on: ubuntu-latest - name: Units (Ⓐ${{ matrix.ansible }}) - strategy: - # As soon as the first unit test fails, cancel the others to free up the CI queue - fail-fast: true - matrix: - ansible: - - stable-2.16 - - stable-2.17 - - stable-2.18 - - devel - - steps: - - name: >- - Perform unit testing against - Ansible version ${{ matrix.ansible }} - uses: felixfontein/ansible-test-gh-action@main - with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} - ansible-core-version: ${{ matrix.ansible }} - codecov-token: ${{ secrets.CODECOV_TOKEN }} - testing-type: units - test-deps: >- - git+https://github.com/ansible-collections/ansible.utils.git,main - git+https://github.com/ansible-collections/ansible.netcommon.git,main - git+https://github.com/ansible-collections/community.internal_test_tools.git,main - - integration: - runs-on: ubuntu-latest - name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }}) - strategy: - fail-fast: false - matrix: - ansible: - - devel - python: - - "3.10" - - "3.11" - - "3.12" - - "3.13" - include: - # 2.15 - - ansible: stable-2.15 - python: "2.7" - - ansible: stable-2.15 - python: "3.6" - - ansible: stable-2.15 - python: "3.7" - # 2.16 - - ansible: stable-2.16 - python: "3.10" - # 2.17 - - ansible: stable-2.17 - python: "3.8" - # 2.18 - - ansible: stable-2.18 - python: "3.9" - - steps: - - name: >- - Perform integration testing against - Ansible version ${{ matrix.ansible }} - under Python ${{ matrix.python }} - uses: felixfontein/ansible-test-gh-action@main - with: - ansible-core-github-repository-slug: ${{ contains(fromJson('["stable-2.14"]'), matrix.ansible) && 'ansible-community/eol-ansible' || 'ansible/ansible' }} - ansible-core-version: ${{ matrix.ansible }} - codecov-token: ${{ secrets.CODECOV_TOKEN }} - integration-continue-on-error: 'false' - integration-diff: 'false' - integration-retry-on-error: 'true' - test-deps: >- - git+https://github.com/ansible-collections/ansible.utils.git,main - git+https://github.com/ansible-collections/ansible.netcommon.git,main - git+https://github.com/ansible-collections/community.internal_test_tools.git,main - target-python-version: ${{ matrix.python }} - testing-type: integration diff --git a/.github/workflows/extra-tests.yml b/.github/workflows/extra-tests.yml deleted file mode 100644 index 0fda77b..0000000 --- a/.github/workflows/extra-tests.yml +++ /dev/null @@ -1,52 +0,0 @@ ---- -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -name: extra-tests -on: - # Run CI against all pushes (direct commits, also merged PRs), Pull Requests - push: - branches: - - main - - stable-* - pull_request: - # Run CI once per day (at 05:15 UTC) - # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version - schedule: - - cron: '15 5 * * *' -env: - NAMESPACE: community - COLLECTION_NAME: routeros - -jobs: - extra-sanity: - name: Extra Sanity - runs-on: ubuntu-latest - steps: - - - name: Check out code - uses: actions/checkout@v4 - with: - path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - persist-credentials: false - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install ansible-core - run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check - - - name: Install collection dependencies - run: | - git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ./ansible_collections/community/internal_test_tools - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.netcommon.git ./ansible_collections/ansible/netcommon - git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.utils.git ./ansible_collections/ansible/utils - # NOTE: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) - # run: ansible-galaxy collection install community.internal_test_tools ansible.netcommon -p . - - - name: Run sanity tests - run: ../../community/internal_test_tools/tools/run.py --color - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} diff --git a/.github/workflows/import-galaxy.yml b/.github/workflows/import-galaxy.yml deleted file mode 100644 index 0c0ee40..0000000 --- a/.github/workflows/import-galaxy.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -name: import-galaxy -'on': - # Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests - push: - branches: - - main - - stable-* - pull_request: - -jobs: - import-galaxy: - permissions: - contents: read - name: Test to import built collection artifact with Galaxy importer - uses: ansible-community/github-action-test-galaxy-import/.github/workflows/test-galaxy-import.yml@main diff --git a/.github/workflows/reuse.yml b/.github/workflows/nox.yml similarity index 50% rename from .github/workflows/reuse.yml rename to .github/workflows/nox.yml index 78cc533..43cce99 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/nox.yml @@ -3,31 +3,33 @@ # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later -name: Verify REUSE - -on: +name: nox +'on': push: branches: - main - stable-* pull_request: - branches: - - main - - stable-* # Run CI once per day (at 05:15 UTC) schedule: - cron: '15 5 * * *' + workflow_dispatch: jobs: - check: - permissions: - contents: read + nox: runs-on: ubuntu-latest - + name: "Run extra sanity tests" steps: - - uses: actions/checkout@v4 + - name: Check out collection + uses: actions/checkout@v4 with: persist-credentials: false + - name: Run nox + uses: ansible-community/antsibull-nox@main - - name: REUSE Compliance Check - uses: fsfe/reuse-action@v5 + ansible-test: + uses: ansible-community/antsibull-nox/.github/workflows/reusable-nox-matrix.yml@main + with: + upload-codecov: true + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md index bdea3c3..2d6aec1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: GPL-3.0-or-later # Community RouterOS Collection [![Documentation](https://img.shields.io/badge/docs-brightgreen.svg)](https://docs.ansible.com/ansible/devel/collections/community/routeros/) -[![CI](https://github.com/ansible-collections/community.routeros/actions/workflows/ansible-test.yml/badge.svg?branch=main)](https://github.com/ansible-collections/community.routeros/actions) +[![CI](https://github.com/ansible-collections/community.routeros/actions/workflows/nox.yml/badge.svg?branch=main)](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) [![REUSE status](https://api.reuse.software/badge/github.com/ansible-collections/community.routeros)](https://api.reuse.software/info/github.com/ansible-collections/community.routeros) diff --git a/antsibull-nox.toml b/antsibull-nox.toml new file mode 100644 index 0000000..6d73110 --- /dev/null +++ b/antsibull-nox.toml @@ -0,0 +1,57 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +[collection_sources] +"community.internal_test_tools" = "git+https://github.com/ansible-collections/community.internal_test_tools.git,main" +"community.netcommon" = "git+https://github.com/ansible-collections/ansible.netcommon.git,main" +"community.utils" = "git+https://github.com/ansible-collections/ansible.utils.git,main" + +[sessions] + +[sessions.lint] +# https://ansible.readthedocs.io/projects/antsibull-nox/config-file/#basic-linting-sessions + +# disable reformatting for now +run_isort = false +run_black = false + +# disable most linters +run_flake8 = false +run_pylint = false +run_yamllint = false +run_mypy = false + +[sessions.docs_check] +validate_collection_refs="all" + +[sessions.extra_checks] +run_no_unwanted_files = true +no_unwanted_files_module_extensions = [".py"] +no_unwanted_files_yaml_extensions = [".yml"] +run_action_groups = true + +[[sessions.extra_checks.action_groups_config]] +name = "api" +pattern = "^api.*$" +exclusions = [] +doc_fragment = "community.routeros.attributes.actiongroup_api" + +[sessions.build_import_check] +run_galaxy_importer = true + +[sessions.ansible_test_sanity] +include_devel = true + +[sessions.ansible_test_units] +include_devel = true + +[sessions.ansible_test_integration_w_default_container] +include_devel = true +controller_python_versions_only = true + +[sessions.ansible_test_integration_w_default_container.core_python_versions] +"2.15" = ["2.7", "3.6", "3.7"] +"2.16" = ["3.10"] +"2.17" = ["3.8"] +"2.18" = ["3.9"] diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..d8c5173 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,50 @@ + +# The following metadata allows Python runners and nox to install the required +# dependencies for running this Python script: +# +# /// script +# dependencies = ["nox>=2025.02.09", "antsibull-nox"] +# /// + +import os +import sys + +import nox + + +# We try to import antsibull-nox, and if that doesn't work, provide a more useful +# error message to the user. +try: + import antsibull_nox +except ImportError: + print("You need to install antsibull-nox in the same Python environment as nox.") + sys.exit(1) + + +IN_CI = os.environ.get("CI") == "true" + + +antsibull_nox.load_antsibull_nox_toml() + + +@nox.session(name="update-docs", default=True) +def update_docs_fragments(session: nox.Session) -> None: + """ + Update/check auto-generated parts of docs fragments. + """ + session.install("ansible-core") + prepare = antsibull_nox.sessions.prepare_collections( + session, install_in_site_packages=True + ) + if not prepare: + return + data = ["python", "tests/update-docs.py"] + if IN_CI: + data.append("--lint") + session.run(*data) + + +# Allow to run the noxfile with `python noxfile.py`, `pipx run noxfile.py`, or similar. +# Requires nox >= 2025.02.09 +if __name__ == "__main__": + nox.main() diff --git a/tests/sanity/extra/action-group.json b/tests/sanity/extra/action-group.json deleted file mode 100644 index db6a92b..0000000 --- a/tests/sanity/extra/action-group.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "include_symlinks": true, - "prefixes": [ - "meta/runtime.yml", - "plugins/modules/", - "tests/sanity/extra/action-group." - ], - "output": "path-message", - "requirements": [ - "pyyaml" - ] -} diff --git a/tests/sanity/extra/action-group.json.license b/tests/sanity/extra/action-group.json.license deleted file mode 100644 index edff8c7..0000000 --- a/tests/sanity/extra/action-group.json.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/action-group.py b/tests/sanity/extra/action-group.py deleted file mode 100755 index cc00945..0000000 --- a/tests/sanity/extra/action-group.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2024, Felix Fontein -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later -"""Make sure all modules that should show up in the action group.""" - -from __future__ import annotations - -import os -import re -import yaml - - -ACTION_GROUPS = { - # The format is as follows: - # * 'pattern': a regular expression matching all module names potentially belonging to the action group; - # * 'exclusions': a list of modules that are not part of the action group; all other modules matching 'pattern' must be part of it; - # * 'doc_fragment': the docs fragment that documents membership of the action group. - 'api': { - 'pattern': re.compile('^api.*$'), - 'exclusions': [], - 'doc_fragment': 'community.routeros.attributes.actiongroup_api', - }, -} - - -def main(): - """Main entry point.""" - - # Load redirects - meta_runtime = 'meta/runtime.yml' - self_path = 'tests/sanity/extra/action-group.py' - try: - with open(meta_runtime, 'rb') as f: - data = yaml.safe_load(f) - action_groups = data['action_groups'] - except Exception as exc: - print(f'{meta_runtime}: cannot load action groups: {exc}') - return - - for action_group in action_groups: - if action_group not in ACTION_GROUPS: - print(f'{meta_runtime}: found unknown action group {action_group!r}; likely {self_path} needs updating') - for action_group, action_group_data in list(ACTION_GROUPS.items()): - if action_group not in action_groups: - print(f'{meta_runtime}: cannot find action group {action_group!r}; likely {self_path} needs updating') - - modules_directory = 'plugins/modules/' - modules_suffix = '.py' - - for file in os.listdir(modules_directory): - if not file.endswith(modules_suffix): - continue - module_name = file[:-len(modules_suffix)] - - for action_group, action_group_data in ACTION_GROUPS.items(): - action_group_content = action_groups.get(action_group) or [] - path = os.path.join(modules_directory, file) - - if not action_group_data['pattern'].match(module_name): - if module_name in action_group_content: - print(f'{path}: module is in action group {action_group!r} despite not matching its pattern as defined in {self_path}') - continue - - should_be_in_action_group = module_name not in action_group_data['exclusions'] - - if should_be_in_action_group: - if module_name not in action_group_content: - print(f'{meta_runtime}: module {module_name!r} is not part of {action_group!r} action group') - else: - action_group_content.remove(module_name) - - documentation = [] - in_docs = False - with open(path, 'r', encoding='utf-8') as f: - for line in f: - if line.startswith('DOCUMENTATION ='): - in_docs = True - elif line.startswith(("'''", '"""')) and in_docs: - in_docs = False - elif in_docs: - documentation.append(line) - if in_docs: - print(f'{path}: cannot find DOCUMENTATION end') - if not documentation: - print(f'{path}: cannot find DOCUMENTATION') - continue - - try: - docs = yaml.safe_load('\n'.join(documentation)) - if not isinstance(docs, dict): - raise Exception('is not a top-level dictionary') - except Exception as exc: - print(f'{path}: cannot load DOCUMENTATION as YAML: {exc}') - continue - - docs_fragments = docs.get('extends_documentation_fragment') or [] - is_in_action_group = action_group_data['doc_fragment'] in docs_fragments - - if should_be_in_action_group != is_in_action_group: - if should_be_in_action_group: - print( - f'{path}: module does not document itself as part of action group {action_group!r}, but it should;' - f' you need to add {action_group_data["doc_fragment"]} to "extends_documentation_fragment" in DOCUMENTATION' - ) - else: - print(f'{path}: module documents itself as part of action group {action_group!r}, but it should not be') - - for action_group, action_group_data in ACTION_GROUPS.items(): - action_group_content = action_groups.get(action_group) or [] - for module_name in action_group_content: - print( - f'{meta_runtime}: module {module_name} mentioned in {action_group!r} action group' - f' does not exist or does not match pattern defined in {self_path}' - ) - - -if __name__ == '__main__': - main() diff --git a/tests/sanity/extra/extra-docs.json b/tests/sanity/extra/extra-docs.json deleted file mode 100644 index 9a28d17..0000000 --- a/tests/sanity/extra/extra-docs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "include_symlinks": false, - "prefixes": [ - "docs/docsite/", - "plugins/", - "roles/" - ], - "output": "path-line-column-message", - "requirements": [ - "ansible-core", - "antsibull-docs" - ] -} diff --git a/tests/sanity/extra/extra-docs.json.license b/tests/sanity/extra/extra-docs.json.license deleted file mode 100644 index edff8c7..0000000 --- a/tests/sanity/extra/extra-docs.json.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/extra-docs.py b/tests/sanity/extra/extra-docs.py deleted file mode 100755 index 251e6d7..0000000 --- a/tests/sanity/extra/extra-docs.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later -"""Check extra collection docs with antsibull-docs.""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import sys -import subprocess - - -def main(): - """Main entry point.""" - env = os.environ.copy() - suffix = ':{env}'.format(env=env["ANSIBLE_COLLECTIONS_PATH"]) if 'ANSIBLE_COLLECTIONS_PATH' in env else '' - env['ANSIBLE_COLLECTIONS_PATH'] = '{root}{suffix}'.format(root=os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd()))), suffix=suffix) - p = subprocess.run( - ['antsibull-docs', 'lint-collection-docs', '--plugin-docs', '--skip-rstcheck', '.'], - env=env, - check=False, - ) - if p.returncode not in (0, 3): - print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) - - -if __name__ == '__main__': - main() diff --git a/tests/sanity/extra/licenses.json b/tests/sanity/extra/licenses.json deleted file mode 100644 index 50e47ca..0000000 --- a/tests/sanity/extra/licenses.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "include_symlinks": false, - "output": "path-message" -} diff --git a/tests/sanity/extra/licenses.json.license b/tests/sanity/extra/licenses.json.license deleted file mode 100644 index edff8c7..0000000 --- a/tests/sanity/extra/licenses.json.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/licenses.py b/tests/sanity/extra/licenses.py deleted file mode 100755 index 80eb795..0000000 --- a/tests/sanity/extra/licenses.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2022, Felix Fontein -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later -"""Prevent files without a correct license identifier from being added to the source tree.""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import glob -import sys - - -def format_license_list(licenses): - if not licenses: - return '(empty)' - return ', '.join(['"%s"' % license for license in licenses]) - - -def find_licenses(filename, relax=False): - spdx_license_identifiers = [] - other_license_identifiers = [] - has_copyright = False - try: - with open(filename, 'r', encoding='utf-8') as f: - for line in f: - line = line.rstrip() - if 'Copyright ' in line: - has_copyright = True - if 'Copyright: ' in line: - print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, )) - if 'SPDX-FileCopyrightText: ' in line: - has_copyright = True - idx = line.find('SPDX-License-Identifier: ') - if idx >= 0: - lic_id = line[idx + len('SPDX-License-Identifier: '):] - spdx_license_identifiers.extend(lic_id.split(' OR ')) - if 'GNU General Public License' in line: - if 'v3.0+' in line: - other_license_identifiers.append('GPL-3.0-or-later') - if 'version 3 or later' in line: - other_license_identifiers.append('GPL-3.0-or-later') - if 'Simplified BSD License' in line: - other_license_identifiers.append('BSD-2-Clause') - if 'Apache License 2.0' in line: - other_license_identifiers.append('Apache-2.0') - if 'PSF License' in line or 'Python-2.0' in line: - other_license_identifiers.append('PSF-2.0') - if 'MIT License' in line: - other_license_identifiers.append('MIT') - except Exception as exc: - print('%s: error while processing file: %s' % (filename, exc)) - if len(set(spdx_license_identifiers)) < len(spdx_license_identifiers): - print('%s: found identical SPDX-License-Identifier values' % (filename, )) - if other_license_identifiers and set(other_license_identifiers) != set(spdx_license_identifiers): - print('%s: SPDX-License-Identifier yielded the license list %s, while manual guessing yielded the license list %s' % ( - filename, format_license_list(spdx_license_identifiers), format_license_list(other_license_identifiers))) - if not has_copyright and not relax: - print('%s: found no copyright notice' % (filename, )) - return sorted(spdx_license_identifiers) - - -def main(): - """Main entry point.""" - paths = sys.argv[1:] or sys.stdin.read().splitlines() - - # The following paths are allowed to have no license identifier - no_comments_allowed = [ - 'changelogs/fragments/*.yml', - 'changelogs/fragments/*.yaml', - ] - - # These files are completely ignored - ignore_paths = [ - '.ansible-test-timeout.json', - '.reuse/dep5', - 'LICENSES/*.txt', - 'COPYING', - ] - - no_comments_allowed = [fn for pattern in no_comments_allowed for fn in glob.glob(pattern)] - ignore_paths = [fn for pattern in ignore_paths for fn in glob.glob(pattern)] - - valid_licenses = [license_file[len('LICENSES/'):-len('.txt')] for license_file in glob.glob('LICENSES/*.txt')] - - for path in paths: - if path.startswith('./'): - path = path[2:] - if path in ignore_paths or path.startswith('tests/output/'): - continue - if os.stat(path).st_size == 0: - continue - if not path.endswith('.license') and os.path.exists(path + '.license'): - path = path + '.license' - valid_licenses_for_path = valid_licenses - if path.startswith('plugins/') and not path.startswith(('plugins/modules/', 'plugins/module_utils/')): - valid_licenses_for_path = [license for license in valid_licenses if license == 'GPL-3.0-or-later'] - licenses = find_licenses(path, relax=path in no_comments_allowed) - if not licenses: - if path not in no_comments_allowed: - print('%s: must have at least one license' % (path, )) - else: - for license in licenses: - if license not in valid_licenses_for_path: - print('%s: found not allowed license "%s", must be one of %s' % ( - path, license, format_license_list(valid_licenses_for_path))) - - -if __name__ == '__main__': - main() diff --git a/tests/sanity/extra/licenses.py.license b/tests/sanity/extra/licenses.py.license deleted file mode 100644 index 6c4958f..0000000 --- a/tests/sanity/extra/licenses.py.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: 2022, Felix Fontein diff --git a/tests/sanity/extra/no-unwanted-files.json b/tests/sanity/extra/no-unwanted-files.json deleted file mode 100644 index c789a7f..0000000 --- a/tests/sanity/extra/no-unwanted-files.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "include_symlinks": true, - "prefixes": [ - "plugins/" - ], - "output": "path-message" -} diff --git a/tests/sanity/extra/no-unwanted-files.json.license b/tests/sanity/extra/no-unwanted-files.json.license deleted file mode 100644 index edff8c7..0000000 --- a/tests/sanity/extra/no-unwanted-files.json.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/no-unwanted-files.py b/tests/sanity/extra/no-unwanted-files.py deleted file mode 100755 index b39df83..0000000 --- a/tests/sanity/extra/no-unwanted-files.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later -"""Prevent unwanted files from being added to the source tree.""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import os -import os.path -import sys - - -def main(): - """Main entry point.""" - paths = sys.argv[1:] or sys.stdin.read().splitlines() - - allowed_extensions = ( - '.cs', - '.ps1', - '.psm1', - '.py', - ) - - skip_paths = set([ - ]) - - skip_directories = ( - ) - - yaml_directories = ( - 'plugins/test/', - 'plugins/filter/', - ) - - for path in paths: - if path in skip_paths: - continue - - if any(path.startswith(skip_directory) for skip_directory in skip_directories): - continue - - if os.path.islink(path): - print('%s: is a symbolic link' % (path, )) - elif not os.path.isfile(path): - print('%s: is not a regular file' % (path, )) - - ext = os.path.splitext(path)[1] - - if ext in ('.yml', ) and any(path.startswith(yaml_directory) for yaml_directory in yaml_directories): - continue - - if ext not in allowed_extensions: - print('%s: extension must be one of: %s' % (path, ', '.join(allowed_extensions))) - - -if __name__ == '__main__': - main() diff --git a/tests/sanity/extra/update-docs.json b/tests/sanity/extra/update-docs.json deleted file mode 100644 index 3a63af8..0000000 --- a/tests/sanity/extra/update-docs.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "include_symlinks": false, - "prefixes": [ - "docs/docsite/rst/api-guide.rst", - "plugins/modules/" - ], - "output": "path-line-column-message", - "requirements": [ - "ansible-core" - ] -} diff --git a/tests/sanity/extra/update-docs.json.license b/tests/sanity/extra/update-docs.json.license deleted file mode 100644 index edff8c7..0000000 --- a/tests/sanity/extra/update-docs.json.license +++ /dev/null @@ -1,3 +0,0 @@ -GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -SPDX-License-Identifier: GPL-3.0-or-later -SPDX-FileCopyrightText: Ansible Project diff --git a/tests/sanity/extra/update-docs.py b/tests/sanity/extra/update-docs.py deleted file mode 100644 index 6015512..0000000 --- a/tests/sanity/extra/update-docs.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later -"""Check whether update-docs.py modifies something.""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import sys -import subprocess - - -def main(): - """Main entry point.""" - p = subprocess.run([sys.executable, 'update-docs.py'], check=False) - if p.returncode not in (0, 1): - print('{0}:0:0: unexpected return code {1}'.format(sys.argv[0], p.returncode)) - - -if __name__ == '__main__': - main() diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt index ece5b29..50c92fb 100644 --- a/tests/sanity/ignore-2.10.txt +++ b/tests/sanity/ignore-2.10.txt @@ -1,9 +1,9 @@ docs/docsite/rst/api-guide.rst rstcheck docs/docsite/rst/quoting.rst rstcheck docs/docsite/rst/ssh-guide.rst rstcheck -update-docs.py compile-2.6 -update-docs.py compile-2.7 -update-docs.py compile-3.5 -update-docs.py future-import-boilerplate -update-docs.py metaclass-boilerplate -update-docs.py shebang +tests/update-docs.py compile-2.6 +tests/update-docs.py compile-2.7 +tests/update-docs.py compile-3.5 +tests/update-docs.py future-import-boilerplate +tests/update-docs.py metaclass-boilerplate +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt index 876765a..1c7f5da 100644 --- a/tests/sanity/ignore-2.11.txt +++ b/tests/sanity/ignore-2.11.txt @@ -1,6 +1,6 @@ -update-docs.py compile-2.6 -update-docs.py compile-2.7 -update-docs.py compile-3.5 -update-docs.py future-import-boilerplate -update-docs.py metaclass-boilerplate -update-docs.py shebang +tests/update-docs.py compile-2.6 +tests/update-docs.py compile-2.7 +tests/update-docs.py compile-3.5 +tests/update-docs.py future-import-boilerplate +tests/update-docs.py metaclass-boilerplate +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.12.txt b/tests/sanity/ignore-2.12.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.12.txt +++ b/tests/sanity/ignore-2.12.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.13.txt +++ b/tests/sanity/ignore-2.13.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.14.txt +++ b/tests/sanity/ignore-2.14.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.15.txt +++ b/tests/sanity/ignore-2.15.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.16.txt b/tests/sanity/ignore-2.16.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.16.txt +++ b/tests/sanity/ignore-2.16.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.17.txt b/tests/sanity/ignore-2.17.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.17.txt +++ b/tests/sanity/ignore-2.17.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.18.txt b/tests/sanity/ignore-2.18.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.18.txt +++ b/tests/sanity/ignore-2.18.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.19.txt b/tests/sanity/ignore-2.19.txt index ce635c3..65e5bca 100644 --- a/tests/sanity/ignore-2.19.txt +++ b/tests/sanity/ignore-2.19.txt @@ -1 +1 @@ -update-docs.py shebang +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt index ece5b29..50c92fb 100644 --- a/tests/sanity/ignore-2.9.txt +++ b/tests/sanity/ignore-2.9.txt @@ -1,9 +1,9 @@ docs/docsite/rst/api-guide.rst rstcheck docs/docsite/rst/quoting.rst rstcheck docs/docsite/rst/ssh-guide.rst rstcheck -update-docs.py compile-2.6 -update-docs.py compile-2.7 -update-docs.py compile-3.5 -update-docs.py future-import-boilerplate -update-docs.py metaclass-boilerplate -update-docs.py shebang +tests/update-docs.py compile-2.6 +tests/update-docs.py compile-2.7 +tests/update-docs.py compile-3.5 +tests/update-docs.py future-import-boilerplate +tests/update-docs.py metaclass-boilerplate +tests/update-docs.py shebang diff --git a/tests/unit/requirements.yml b/tests/unit/requirements.yml index 6a22736..107fe12 100644 --- a/tests/unit/requirements.yml +++ b/tests/unit/requirements.yml @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-3.0-or-later collections: -- ansible.netcommon + - community.internal_test_tools diff --git a/update-docs.py b/tests/update-docs.py old mode 100755 new mode 100644 similarity index 62% rename from update-docs.py rename to tests/update-docs.py index 4f164c8..5f28f8e --- a/update-docs.py +++ b/tests/update-docs.py @@ -11,9 +11,6 @@ Updates DOCUMENTATION of modules using module_utils._api_data with the correct l import sys -# Ensure that we can import things from ansible_collections -sys.path.append('../../..') - from ansible_collections.community.routeros.plugins.module_utils._api_data import ( PATHS, join_path, @@ -26,24 +23,34 @@ MODULES = [ ] -def update_file(file, begin_line, end_line, choice_line, path_choices): +def update_file(file: str, begin_line: str, end_line: str, choice_line: str, path_choices: list[str]) -> bool: with open(file, 'r', encoding='utf-8') as f: lines = f.read().splitlines() begin_index = lines.index(begin_line) end_index = lines.index(end_line, begin_index + 1) new_lines = lines[:begin_index + 1] + [choice_line.format(choice=choice) for choice in path_choices] + lines[end_index:] - if lines != new_lines: - print(f'{file} has been updated') - with open(file, 'w', encoding='utf-8') as f: - f.write('\n'.join(new_lines) + '\n') + if lines == new_lines: + return False + print(f'{file} has been updated') + with open(file, 'w', encoding='utf-8') as f: + f.write('\n'.join(new_lines) + '\n') + return True -def main(): +def main(args: list[str]) -> int: path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if path_info.fully_understood]) + changes = False for file in MODULES: - update_file(file, ' # BEGIN PATH LIST', ' # END PATH LIST', ' - {choice}', path_choices) + changes |= update_file(file, ' # BEGIN PATH LIST', ' # END PATH LIST', ' - {choice}', path_choices) + + lint = "--lint" in args + if not lint or not changes: + return 0 + + print("Run 'nox -Re update-docs'!") + return 1 if __name__ == '__main__': - main() + sys.exit(main(sys.argv[1:])) From 4b9925ac23c17c2723c0b0ac7cb87ac646107476 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 19 Apr 2025 13:11:42 +0200 Subject: [PATCH 325/365] Re-add reuse check. --- antsibull-nox.toml | 2 ++ noxfile.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 6d73110..541f4e7 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -25,6 +25,8 @@ run_mypy = false [sessions.docs_check] validate_collection_refs="all" +[sessions.license_check] + [sessions.extra_checks] run_no_unwanted_files = true no_unwanted_files_module_extensions = [".py"] diff --git a/noxfile.py b/noxfile.py index d8c5173..16187f9 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,3 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later # The following metadata allows Python runners and nox to install the required # dependencies for running this Python script: From 770e4d2c8dfc9eb661aee19b27abda6430acde81 Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 20 Apr 2025 21:48:26 +0200 Subject: [PATCH 326/365] Rename Wireguard peer "is-responder" to "responder" for RouterOS 7.17 (#364) RouterOS 7.17 renamed the `is-responder` property in `/interface/wireguard/peers` to `responder`. --- changelogs/fragments/364-wireguard-responder.yml | 2 ++ plugins/module_utils/_api_data.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/364-wireguard-responder.yml diff --git a/changelogs/fragments/364-wireguard-responder.yml b/changelogs/fragments/364-wireguard-responder.yml new file mode 100644 index 0000000..73cd675 --- /dev/null +++ b/changelogs/fragments/364-wireguard-responder.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - rename ``is-responder`` property in ``interface wireguard peers`` to ``responder`` for RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/364). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 10a6216..222155d 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -2441,7 +2441,8 @@ PATHS = { }, versioned_fields=[ ([('7.15', '>=')], 'name', KeyInfo()), - ([('7.15', '>=')], 'is-responder', KeyInfo()), + ([('7.15', '>='), ('7.17', '<')], 'is-responder', KeyInfo()), + ([('7.17', '>=')], 'responder', KeyInfo()), ], ), ), From 81237dbde4d0495680e23366d7098a368cae7e0a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 20 Apr 2025 21:49:40 +0200 Subject: [PATCH 327/365] Prepare 3.6.0. --- changelogs/fragments/3.6.0.yml | 1 + changelogs/fragments/360-bgp-connection-afi.yml | 2 +- galaxy.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/3.6.0.yml diff --git a/changelogs/fragments/3.6.0.yml b/changelogs/fragments/3.6.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.6.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/changelogs/fragments/360-bgp-connection-afi.yml b/changelogs/fragments/360-bgp-connection-afi.yml index 13e89ea..ff73916 100644 --- a/changelogs/fragments/360-bgp-connection-afi.yml +++ b/changelogs/fragments/360-bgp-connection-afi.yml @@ -1,2 +1,2 @@ minor_changes: - - api_modify, api_info - field name change in ``routing bgp connection`` path implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). + - api_info, api_modify - field name change in ``routing bgp connection`` path implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). diff --git a/galaxy.yml b/galaxy.yml index 3557098..2bd801f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.5.0 +version: 3.6.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 180e87fd5dd000d1e646491676fa6fd39684ad7e Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 21 Apr 2025 13:40:42 +0200 Subject: [PATCH 328/365] Release 3.6.0. --- CHANGELOG.md | 262 ++++++++++-------- CHANGELOG.rst | 15 + changelogs/changelog.yaml | 16 ++ changelogs/fragments/3.6.0.yml | 1 - .../fragments/358-mdns-repeat-ifaces.yml | 2 - .../fragments/360-bgp-connection-afi.yml | 2 - .../fragments/364-wireguard-responder.yml | 2 - 7 files changed, 171 insertions(+), 129 deletions(-) delete mode 100644 changelogs/fragments/3.6.0.yml delete mode 100644 changelogs/fragments/358-mdns-repeat-ifaces.yml delete mode 100644 changelogs/fragments/360-bgp-connection-afi.yml delete mode 100644 changelogs/fragments/364-wireguard-responder.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9b85b..136ba21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,147 +2,150 @@ **Topics** -- v3\.5\.0 +- v3\.6\.0 - Release Summary - Minor Changes -- v3\.4\.0 +- v3\.5\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.5\.0 + +## v3\.6\.0 ### Release Summary @@ -152,17 +155,32 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. +* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. +* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. + + +## v3\.5\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- change default for /ip/cloud/ddns\-enabled for RouterOS 7\.17 and newer from yes to auto \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\. ## v3\.4\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. @@ -175,12 +193,12 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. @@ -191,12 +209,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -204,12 +222,12 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -222,7 +240,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -240,12 +258,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -256,12 +274,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -273,12 +291,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -302,12 +320,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -317,12 +335,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -331,12 +349,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -353,12 +371,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -368,12 +386,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -387,12 +405,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -406,12 +424,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -426,12 +444,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -463,12 +481,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -482,7 +500,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -503,7 +521,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -516,7 +534,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -529,12 +547,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -554,12 +572,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -572,12 +590,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -592,12 +610,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -610,12 +628,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -654,7 +672,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -667,12 +685,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -687,7 +705,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -701,12 +719,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -725,12 +743,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -754,12 +772,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -795,12 +813,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -816,12 +834,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -830,7 +848,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -843,7 +861,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -856,7 +874,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -869,12 +887,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6a82da8..744afef 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,21 @@ Community RouterOS Release Notes .. contents:: Topics +v3.6.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add ``mdns-repeat-ifaces`` to ``ip dns`` for RouterOS 7.16 and newer (https://github.com/ansible-collections/community.routeros/pull/358). +- api_info, api_modify - field name change in ``routing bgp connection`` path implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). +- api_info, api_modify - rename ``is-responder`` property in ``interface wireguard peers`` to ``responder`` for RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/364). + v3.5.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index ee957d5..5bb0119 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -885,3 +885,19 @@ releases: - 3.5.0.yml - 350-ip-cloud-ddns-enabled-auto.yml release_date: '2025-03-22' + 3.6.0: + changes: + minor_changes: + - api_info, api_modify - add ``mdns-repeat-ifaces`` to ``ip dns`` for RouterOS + 7.16 and newer (https://github.com/ansible-collections/community.routeros/pull/358). + - api_info, api_modify - field name change in ``routing bgp connection`` path + implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). + - api_info, api_modify - rename ``is-responder`` property in ``interface wireguard + peers`` to ``responder`` for RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/364). + release_summary: Feature release. + fragments: + - 3.6.0.yml + - 358-mdns-repeat-ifaces.yml + - 360-bgp-connection-afi.yml + - 364-wireguard-responder.yml + release_date: '2025-04-21' diff --git a/changelogs/fragments/3.6.0.yml b/changelogs/fragments/3.6.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.6.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/358-mdns-repeat-ifaces.yml b/changelogs/fragments/358-mdns-repeat-ifaces.yml deleted file mode 100644 index 3cd6d62..0000000 --- a/changelogs/fragments/358-mdns-repeat-ifaces.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``mdns-repeat-ifaces`` to ``ip dns`` for RouterOS 7.16 and newer (https://github.com/ansible-collections/community.routeros/pull/358). diff --git a/changelogs/fragments/360-bgp-connection-afi.yml b/changelogs/fragments/360-bgp-connection-afi.yml deleted file mode 100644 index ff73916..0000000 --- a/changelogs/fragments/360-bgp-connection-afi.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - field name change in ``routing bgp connection`` path implemented by RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/360). diff --git a/changelogs/fragments/364-wireguard-responder.yml b/changelogs/fragments/364-wireguard-responder.yml deleted file mode 100644 index 73cd675..0000000 --- a/changelogs/fragments/364-wireguard-responder.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - rename ``is-responder`` property in ``interface wireguard peers`` to ``responder`` for RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/364). From d1db4bec9210ac12678f7f814eb4bf24809831df Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 24 Apr 2025 20:38:56 +0200 Subject: [PATCH 329/365] Adjust EE tests. (#366) --- tests/ee/roles/filter_quoting/tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ee/roles/filter_quoting/tasks/main.yml b/tests/ee/roles/filter_quoting/tasks/main.yml index e7a2d29..c80af59 100644 --- a/tests/ee/roles/filter_quoting/tasks/main.yml +++ b/tests/ee/roles/filter_quoting/tasks/main.yml @@ -22,7 +22,7 @@ assert: that: - >- - result.msg == "Unexpected end of string during escaped parameter" + "Unexpected end of string during escaped parameter" in result.msg - name: "Test quote_argument filter" assert: From e52978b6d262cfb1772b6c2d6b6d6a33de428a43 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 24 Apr 2025 22:48:23 +0200 Subject: [PATCH 330/365] Fix info on blanket license statement for changelog fragments. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d6aec1..59d2aa4 100644 --- a/README.md +++ b/README.md @@ -208,4 +208,4 @@ See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/commu Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.routeros/blob/main/LICENSES/BSD-2-Clause.txt). -All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `.reuse/dep5`. This conforms to the [REUSE specification](https://reuse.software/spec/). +All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `REUSE.toml`. This conforms to the [REUSE specification](https://reuse.software/spec/). From 3af45c33f1b1e008cf59e9adbbb73068b39170be Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Apr 2025 09:07:00 +0200 Subject: [PATCH 331/365] Add yamllint to antsibull-nox and add config files. --- .gitignore | 1 + .yamllint | 53 +++++++++++++++++++++++++++++++++++++++++++++ .yamllint-docs | 54 ++++++++++++++++++++++++++++++++++++++++++++++ .yamllint-examples | 54 ++++++++++++++++++++++++++++++++++++++++++++++ antsibull-nox.toml | 10 ++++----- 5 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 .yamllint create mode 100644 .yamllint-docs create mode 100644 .yamllint-examples diff --git a/.gitignore b/.gitignore index 8e398ff..728531b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /tests/output/ /changelogs/.plugin-cache.yaml +/tests/integration/inventory # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..a6707e2 --- /dev/null +++ b/.yamllint @@ -0,0 +1,53 @@ +--- +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: 2025 Felix Fontein + +extends: default + +ignore: | + /changelogs/ + +rules: + line-length: + max: 300 + level: error + document-start: + present: true + document-end: false + truthy: + level: error + allowed-values: + - 'true' + - 'false' + indentation: + spaces: 2 + indent-sequences: true + key-duplicates: enable + trailing-spaces: enable + new-line-at-end-of-file: disable + hyphens: + max-spaces-after: 1 + empty-lines: + max: 2 + max-start: 0 + max-end: 0 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true + comments: + min-spaces-from-content: 1 + comments-indentation: false diff --git a/.yamllint-docs b/.yamllint-docs new file mode 100644 index 0000000..de8947d --- /dev/null +++ b/.yamllint-docs @@ -0,0 +1,54 @@ +--- +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: 2025 Felix Fontein + +extends: default + +ignore: | + /changelogs/ + +rules: + line-length: + max: 160 + level: error + document-start: + present: false + document-end: + present: false + truthy: + level: error + allowed-values: + - 'true' + - 'false' + indentation: + spaces: 2 + indent-sequences: true + key-duplicates: enable + trailing-spaces: enable + new-line-at-end-of-file: disable + hyphens: + max-spaces-after: 1 + empty-lines: + max: 2 + max-start: 0 + max-end: 0 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true + comments: + min-spaces-from-content: 1 + comments-indentation: false diff --git a/.yamllint-examples b/.yamllint-examples new file mode 100644 index 0000000..062ac5a --- /dev/null +++ b/.yamllint-examples @@ -0,0 +1,54 @@ +--- +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: 2025 Felix Fontein + +extends: default + +ignore: | + /changelogs/ + +rules: + line-length: + max: 160 + level: error + document-start: + present: true + document-end: + present: false + truthy: + level: error + allowed-values: + - 'true' + - 'false' + indentation: + spaces: 2 + indent-sequences: true + key-duplicates: enable + trailing-spaces: enable + new-line-at-end-of-file: disable + hyphens: + max-spaces-after: 1 + empty-lines: + max: 2 + max-start: 0 + max-end: 0 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true + comments: + min-spaces-from-content: 1 + comments-indentation: false diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 541f4e7..d95dfed 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -10,16 +10,14 @@ [sessions] [sessions.lint] -# https://ansible.readthedocs.io/projects/antsibull-nox/config-file/#basic-linting-sessions - -# disable reformatting for now run_isort = false run_black = false - -# disable most linters run_flake8 = false run_pylint = false -run_yamllint = false +run_yamllint = true +yamllint_config = ".yamllint" +yamllint_config_plugins = ".yamllint-docs" +yamllint_config_plugins_examples = ".yamllint-examples" run_mypy = false [sessions.docs_check] From 08152376de116e7d933d19ee25318f7a2eb222ae Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Apr 2025 09:21:32 +0200 Subject: [PATCH 332/365] Fix linting errors. --- .github/workflows/docs-pr.yml | 2 +- .github/workflows/docs-push.yml | 2 +- .github/workflows/ee.yml | 2 +- galaxy.yml | 2 +- plugins/filter/join.yml | 1 + plugins/filter/list_to_dict.yml | 1 + plugins/filter/quote_argument.yml | 4 +++- plugins/filter/quote_argument_value.yml | 4 +++- plugins/filter/split.yml | 4 +++- plugins/modules/api.py | 1 + plugins/modules/api_facts.py | 1 + plugins/modules/api_find_and_modify.py | 1 + plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + plugins/modules/command.py | 1 + plugins/modules/facts.py | 1 + tests/integration/requirements.yml | 2 +- 17 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 7d35e5c..63135a1 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -7,7 +7,7 @@ name: Collection Docs concurrency: group: docs-pr-${{ github.head_ref }} cancel-in-progress: true -on: +'on': pull_request_target: types: [opened, synchronize, reopened, closed] diff --git a/.github/workflows/docs-push.yml b/.github/workflows/docs-push.yml index 80f62f5..3d2c2b1 100644 --- a/.github/workflows/docs-push.yml +++ b/.github/workflows/docs-push.yml @@ -7,7 +7,7 @@ name: Collection Docs concurrency: group: docs-push-${{ github.sha }} cancel-in-progress: true -on: +'on': push: branches: - main diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index b04d197..5b45972 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later name: execution environment -on: +'on': # Run CI against all pushes (direct commits, also merged PRs), Pull Requests push: branches: diff --git a/galaxy.yml b/galaxy.yml index 2bd801f..b943229 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -16,7 +16,7 @@ authors: description: Modules and plugins for MikroTik RouterOS license: - GPL-3.0-or-later -#license_file: COPYING +# license_file: COPYING tags: - network - mikrotik diff --git a/plugins/filter/join.yml b/plugins/filter/join.yml index 9ff8a50..f25d739 100644 --- a/plugins/filter/join.yml +++ b/plugins/filter/join.yml @@ -20,6 +20,7 @@ DOCUMENTATION: - Felix Fontein (@felixfontein) EXAMPLES: | + --- - name: Join arguments for a RouterOS CLI command ansible.builtin.set_fact: arguments: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.join }}" diff --git a/plugins/filter/list_to_dict.yml b/plugins/filter/list_to_dict.yml index 6e7992d..7b7c5b1 100644 --- a/plugins/filter/list_to_dict.yml +++ b/plugins/filter/list_to_dict.yml @@ -30,6 +30,7 @@ DOCUMENTATION: - Felix Fontein (@felixfontein) EXAMPLES: | + --- - name: Convert a list to a dictionary ansible.builtin.set_fact: dictionary: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict }}" diff --git a/plugins/filter/quote_argument.yml b/plugins/filter/quote_argument.yml index 26a1f04..477a15e 100644 --- a/plugins/filter/quote_argument.yml +++ b/plugins/filter/quote_argument.yml @@ -19,9 +19,11 @@ DOCUMENTATION: - Felix Fontein (@felixfontein) EXAMPLES: | + --- - name: Quote a RouterOS CLI command argument ansible.builtin.set_fact: - quoted: "{{ 'comment=this is a "comment"' | community.routeros.quote_argument }}" + quoted: >- + {{ 'comment=this is a "comment"' | community.routeros.quote_argument }} # Should result in 'comment="this is a \"comment\""' RETURN: diff --git a/plugins/filter/quote_argument_value.yml b/plugins/filter/quote_argument_value.yml index 839895b..b4da246 100644 --- a/plugins/filter/quote_argument_value.yml +++ b/plugins/filter/quote_argument_value.yml @@ -19,9 +19,11 @@ DOCUMENTATION: - Felix Fontein (@felixfontein) EXAMPLES: | + --- - name: Quote a RouterOS CLI command argument's value ansible.builtin.set_fact: - quoted: "{{ 'this is a "comment"' | community.routeros.quote_argument_value }}" + quoted: >- + {{ 'this is a "comment"' | community.routeros.quote_argument_value }} # Should result in '"this is a \"comment\""' RETURN: diff --git a/plugins/filter/split.yml b/plugins/filter/split.yml index 5fc4b30..cb4ba88 100644 --- a/plugins/filter/split.yml +++ b/plugins/filter/split.yml @@ -19,9 +19,11 @@ DOCUMENTATION: - Felix Fontein (@felixfontein) EXAMPLES: | + --- - name: Split command into list of arguments ansible.builtin.set_fact: - argument_list: "{{ 'foo=bar comment="foo is bar" baz' | community.routeros.split }}" + argument_list: >- + {{ 'foo=bar comment="foo is bar" baz' | community.routeros.split }} # Should result in ['foo=bar', 'comment=foo is bar', 'baz'] RETURN: diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 4e42912..d3ec089 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -164,6 +164,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Get example - ip address print community.routeros.api: hostname: "{{ hostname }}" diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index b6d1261..41c9a4e 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -55,6 +55,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Collect all facts from the device community.routeros.api_facts: hostname: 192.168.88.1 diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 817451c..2d465e8 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -83,6 +83,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Rename bridge from 'bridge' to 'my-bridge' community.routeros.api_find_and_modify: hostname: "{{ hostname }}" diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index b94e987..bd36955 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -324,6 +324,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Get IP addresses community.routeros.api_info: hostname: "{{ hostname }}" diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 1fb4dae..2c1b012 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -360,6 +360,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Setup DHCP server networks # Ensures that we have exactly two DHCP server networks (in the specified order) community.routeros.api_modify: diff --git a/plugins/modules/command.py b/plugins/modules/command.py index 90f9733..50abe49 100644 --- a/plugins/modules/command.py +++ b/plugins/modules/command.py @@ -77,6 +77,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Run command on remote devices community.routeros.command: commands: /system routerboard print diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index 7b169b7..e75d609 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -42,6 +42,7 @@ seealso: """ EXAMPLES = r""" +--- - name: Collect all facts from the device community.routeros.facts: gather_subset: all diff --git a/tests/integration/requirements.yml b/tests/integration/requirements.yml index 6a22736..559c301 100644 --- a/tests/integration/requirements.yml +++ b/tests/integration/requirements.yml @@ -4,4 +4,4 @@ # SPDX-License-Identifier: GPL-3.0-or-later collections: -- ansible.netcommon + - ansible.netcommon From 5b81c157fe8b83ced876ca61545b51ab996c2064 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Apr 2025 12:22:44 +0200 Subject: [PATCH 333/365] Add reformat commit to .git-blame-ignore-revs. --- .git-blame-ignore-revs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..9623a78 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,6 @@ +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +# Reformat YAML: https://github.com/ansible-collections/community.routeros/pull/369 +08152376de116e7d933d19ee25318f7a2eb222ae From f5b952751e4fbaaf84997ec2a809fac3ca60d8e9 Mon Sep 17 00:00:00 2001 From: Michael Jenny Date: Thu, 29 May 2025 14:58:38 +0200 Subject: [PATCH 334/365] Update _api_data.py (#371) * Update _api_data.py Add /interface/bridge property "port-cost-mode" which is supported since RouterOS 7.13. See changelog for details: https://mikrotik.com/download/changelogs * Create 371-add-bridge-port-cost-mode.yml * Update changelogs/fragments/371-add-bridge-port-cost-mode.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/371-add-bridge-port-cost-mode.yml | 3 +++ plugins/module_utils/_api_data.py | 1 + 2 files changed, 4 insertions(+) create mode 100644 changelogs/fragments/371-add-bridge-port-cost-mode.yml diff --git a/changelogs/fragments/371-add-bridge-port-cost-mode.yml b/changelogs/fragments/371-add-bridge-port-cost-mode.yml new file mode 100644 index 0000000..5ec9177 --- /dev/null +++ b/changelogs/fragments/371-add-bridge-port-cost-mode.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - api_info, api_modify - add ``port-cost-mode`` to ``interface bridge`` which is supported since RouterOS 7.13 (https://github.com/ansible-collections/community.routeros/pull/371). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 222155d..e95d599 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -281,6 +281,7 @@ PATHS = { versioned_fields=[ ([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)), ([('7.0', '>=')], 'ingress-filtering', KeyInfo(default=True)), + ([('7.13', '>=')], 'port-cost-mode', KeyInfo(default='long')), ([('7.16', '>=')], 'forward-reserved-addresses', KeyInfo(default=False)), ([('7.16', '>=')], 'max-learned-entries', KeyInfo(default='auto')), ], From bfd6b0bb13423f284dab60eeb43b43ec8048e5c6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 29 May 2025 14:59:45 +0200 Subject: [PATCH 335/365] Prepare 3.7.0. --- changelogs/fragments/3.7.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.7.0.yml diff --git a/changelogs/fragments/3.7.0.yml b/changelogs/fragments/3.7.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.7.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index b943229..b9f4453 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.6.0 +version: 3.7.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From ab1026504c08c5bb1844cbcde7505b40b79261b2 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 31 May 2025 16:50:52 +0200 Subject: [PATCH 336/365] Allow to ignore dynamic and builtin entries. (#373) --- ...73-api_find_and_modify-dynamic-builtin.yml | 2 + plugins/modules/api_find_and_modify.py | 48 +++++++++++-- .../modules/test_api_find_and_modify.py | 72 +++++++++++++++++++ 3 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml diff --git a/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml b/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml new file mode 100644 index 0000000..20e7a6b --- /dev/null +++ b/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml @@ -0,0 +1,2 @@ +minor_changes: + - "api_find_and_modify - allow to control whether ``dynamic`` and/or ``builtin`` entries are ignored with the new ``ignore_dynamic`` and ``ignore_builtin`` options (https://github.com/ansible-collections/community.routeros/issues/372, https://github.com/ansible-collections/community.routeros/pull/373)." diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 2d465e8..acdd125 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -75,6 +75,22 @@ options: - Whether to allow that no match is found. - If not specified, this value is induced from whether O(require_matches_min) is 0 or larger. type: bool + ignore_dynamic: + description: + - Whether to ignore dynamic entries. + - By default, they are considered. If set to V(true), they are not considered. + - It is generally recommended to set this to V(true) unless when you really need to modify dynamic entries. + type: bool + default: false + version_added: 3.7.0 + ignore_builtin: + description: + - Whether to ignore builtin entries. + - By default, they are considered. If set to V(true), they are not considered. + - It is generally recommended to set this to V(true) unless when you really need to modify builtin entries. + type: bool + default: false + version_added: 3.7.0 seealso: - module: community.routeros.api - module: community.routeros.api_facts @@ -94,6 +110,10 @@ EXAMPLES = r""" name: bridge values: name: my-bridge + # Always ignore dynamic and builtin entries + # (not relevant for this path, but generally recommended) + ignore_dynamic: true + ignore_builtin: true - name: Change IP address to 192.168.1.1 for interface bridge - assuming there is only one community.routeros.api_find_and_modify: @@ -105,10 +125,14 @@ EXAMPLES = r""" interface: bridge values: address: "192.168.1.1/24" - # If there are zero entries, or more than one: fail! We expected that - # exactly one is configured. + # If there are zero entries, or more than one: fail! We expected that + # exactly one is configured. require_matches_min: 1 require_matches_max: 1 + # Always ignore dynamic and builtin entries + # (not relevant for this path, but generally recommended) + ignore_dynamic: true + ignore_builtin: true """ RETURN = r""" @@ -185,6 +209,17 @@ def compose_api_path(api, path): return api_path +def filter_entries(entries, ignore_dynamic=False, ignore_builtin=False): + result = [] + for entry in entries: + if ignore_dynamic and entry.get('dynamic', False): + continue + if ignore_builtin and entry.get('builtin', False): + continue + result.append(entry) + return result + + DISABLED_MEANS_EMPTY_STRING = ('comment', ) @@ -196,6 +231,8 @@ def main(): require_matches_min=dict(type='int', default=0), require_matches_max=dict(type='int'), allow_no_matches=dict(type='bool'), + ignore_dynamic=dict(type='bool', default=False), + ignore_builtin=dict(type='bool', default=False), ) module_args.update(api_argument_spec()) @@ -223,6 +260,9 @@ def main(): if key in values: module.fail_json(msg='`values` must not contain both "{key}" and "!{key}"!'.format(key=key)) + ignore_dynamic = module.params['ignore_dynamic'] + ignore_builtin = module.params['ignore_builtin'] + check_has_library(module) api = create_api(module) @@ -230,7 +270,7 @@ def main(): api_path = compose_api_path(api, path) - old_data = list(api_path) + old_data = filter_entries(list(api_path), ignore_dynamic=ignore_dynamic, ignore_builtin=ignore_builtin) new_data = [entry.copy() for entry in old_data] # Find matching entries @@ -299,7 +339,7 @@ def main(): error=to_native(e), ) ) - new_data = list(api_path) + new_data = filter_entries(list(api_path), ignore_dynamic=ignore_dynamic, ignore_builtin=ignore_builtin) # Produce return value more = {} diff --git a/tests/unit/plugins/modules/test_api_find_and_modify.py b/tests/unit/plugins/modules/test_api_find_and_modify.py index fe5e180..e700f9d 100644 --- a/tests/unit/plugins/modules/test_api_find_and_modify.py +++ b/tests/unit/plugins/modules/test_api_find_and_modify.py @@ -94,6 +94,52 @@ START_IP_FIREWALL_FILTER = [ START_IP_FIREWALL_FILTER_OLD_DATA = massage_expected_result_data(START_IP_FIREWALL_FILTER, ('ip', 'firewall', 'filter'), keep_all=True) +START_IP_SERVICE = [ + # I removed all entryes not for 'api' and 'api-ssl' + { + "certificate": None, + "tls-version": None, + ".id": "*7", + "address": "", + "disabled": True, + "dynamic": False, + "invalid": True, + "name": "api", + "port": 8728, + "proto": "tcp", + "vrf": "main" + }, + { + ".id": "*9", + "address": "192.168.1.0/24", + "certificate": "mycert", + "dynamic": False, + "invalid": False, + "name": "api-ssl", + "port": 8729, + "proto": "tcp", + "tls-version": "only-1.2", + "vrf": "main" + }, + { + "address": None, + "certificate": None, + "max-sessions": None, + "tls-version": None, + ".id": "*13", + "connection": True, + "dynamic": True, + "invalid": False, + "local": "192.168.1.1", + "name": "api-ssl", + "port": 8729, + "proto": "tcp", + "remote": "192.168.1.2:12346" + } +] + +START_IP_SERVICE_OLD_DATA = massage_expected_result_data(START_IP_SERVICE, ('ip', 'service'), keep_all=True) + class TestRouterosApiFindAndModifyModule(ModuleTestCase): @@ -685,3 +731,29 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase): ]) self.assertEqual(result['match_count'], 3) self.assertEqual(result['modify_count'], 2) + + @patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path', + new=create_fake_path(('ip', 'service'), START_IP_SERVICE)) + def test_change_ignore_dynamic(self): + with self.assertRaises(AnsibleExitJson) as exc: + args = self.config_module_args.copy() + args.update({ + 'path': 'ip service', + 'find': { + 'name': 'api-ssl', + }, + 'values': { + 'address': '192.168.1.0/24', + }, + 'ignore_dynamic': True, + '_ansible_diff': True, + }) + with set_module_args(args): + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result['changed'], False) + self.assertEqual(result['old_data'], [entry for entry in START_IP_SERVICE_OLD_DATA if entry["dynamic"] is False]) + self.assertEqual(result['new_data'], [entry for entry in START_IP_SERVICE_OLD_DATA if entry["dynamic"] is False]) + self.assertEqual(result['match_count'], 1) + self.assertEqual(result['modify_count'], 0) From 221a697af9dc92238922d105384e69ce36f9906f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 31 May 2025 16:57:51 +0200 Subject: [PATCH 337/365] Release 3.7.0. --- CHANGELOG.md | 273 ++++++++++-------- CHANGELOG.rst | 14 + changelogs/changelog.yaml | 15 + changelogs/fragments/3.7.0.yml | 1 - .../371-add-bridge-port-cost-mode.yml | 3 - ...73-api_find_and_modify-dynamic-builtin.yml | 2 - 6 files changed, 174 insertions(+), 134 deletions(-) delete mode 100644 changelogs/fragments/3.7.0.yml delete mode 100644 changelogs/fragments/371-add-bridge-port-cost-mode.yml delete mode 100644 changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 136ba21..294687e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,150 +2,153 @@ **Topics** -- v3\.6\.0 +- v3\.7\.0 - Release Summary - Minor Changes -- v3\.5\.0 +- v3\.6\.0 - Release Summary - Minor Changes -- v3\.4\.0 +- v3\.5\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.6\.0 + +## v3\.7\.0 ### Release Summary @@ -155,12 +158,11 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. -* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. -* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. +* api\_find\_and\_modify \- allow to control whether dynamic and/or builtin entries are ignored with the new ignore\_dynamic and ignore\_builtin options \([https\://github\.com/ansible\-collections/community\.routeros/issues/372](https\://github\.com/ansible\-collections/community\.routeros/issues/372)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/373](https\://github\.com/ansible\-collections/community\.routeros/pull/373)\)\. +* api\_info\, api\_modify \- add port\-cost\-mode to interface bridge which is supported since RouterOS 7\.13 \([https\://github\.com/ansible\-collections/community\.routeros/pull/371](https\://github\.com/ansible\-collections/community\.routeros/pull/371)\)\. - -## v3\.5\.0 + +## v3\.6\.0 ### Release Summary @@ -170,17 +172,32 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. +* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. +* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. + + +## v3\.5\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- change default for /ip/cloud/ddns\-enabled for RouterOS 7\.17 and newer from yes to auto \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\. ## v3\.4\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. @@ -193,12 +210,12 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. @@ -209,12 +226,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -222,12 +239,12 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -240,7 +257,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -258,12 +275,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -274,12 +291,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -291,12 +308,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -320,12 +337,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -335,12 +352,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -349,12 +366,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -371,12 +388,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -386,12 +403,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -405,12 +422,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -424,12 +441,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -444,12 +461,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -481,12 +498,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -500,7 +517,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -521,7 +538,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -534,7 +551,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -547,12 +564,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -572,12 +589,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -590,12 +607,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -610,12 +627,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -628,12 +645,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -672,7 +689,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -685,12 +702,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -705,7 +722,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -719,12 +736,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -743,12 +760,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -772,12 +789,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -813,12 +830,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -834,12 +851,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -848,7 +865,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -861,7 +878,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -874,7 +891,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -887,12 +904,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 744afef..627304d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,20 @@ Community RouterOS Release Notes .. contents:: Topics +v3.7.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_find_and_modify - allow to control whether ``dynamic`` and/or ``builtin`` entries are ignored with the new ``ignore_dynamic`` and ``ignore_builtin`` options (https://github.com/ansible-collections/community.routeros/issues/372, https://github.com/ansible-collections/community.routeros/pull/373). +- api_info, api_modify - add ``port-cost-mode`` to ``interface bridge`` which is supported since RouterOS 7.13 (https://github.com/ansible-collections/community.routeros/pull/371). + v3.6.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 5bb0119..3297286 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -901,3 +901,18 @@ releases: - 360-bgp-connection-afi.yml - 364-wireguard-responder.yml release_date: '2025-04-21' + 3.7.0: + changes: + minor_changes: + - api_find_and_modify - allow to control whether ``dynamic`` and/or ``builtin`` + entries are ignored with the new ``ignore_dynamic`` and ``ignore_builtin`` + options (https://github.com/ansible-collections/community.routeros/issues/372, + https://github.com/ansible-collections/community.routeros/pull/373). + - api_info, api_modify - add ``port-cost-mode`` to ``interface bridge`` which + is supported since RouterOS 7.13 (https://github.com/ansible-collections/community.routeros/pull/371). + release_summary: Feature release. + fragments: + - 3.7.0.yml + - 371-add-bridge-port-cost-mode.yml + - 373-api_find_and_modify-dynamic-builtin.yml + release_date: '2025-05-31' diff --git a/changelogs/fragments/3.7.0.yml b/changelogs/fragments/3.7.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.7.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/371-add-bridge-port-cost-mode.yml b/changelogs/fragments/371-add-bridge-port-cost-mode.yml deleted file mode 100644 index 5ec9177..0000000 --- a/changelogs/fragments/371-add-bridge-port-cost-mode.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - api_info, api_modify - add ``port-cost-mode`` to ``interface bridge`` which is supported since RouterOS 7.13 (https://github.com/ansible-collections/community.routeros/pull/371). diff --git a/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml b/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml deleted file mode 100644 index 20e7a6b..0000000 --- a/changelogs/fragments/373-api_find_and_modify-dynamic-builtin.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - "api_find_and_modify - allow to control whether ``dynamic`` and/or ``builtin`` entries are ignored with the new ``ignore_dynamic`` and ``ignore_builtin`` options (https://github.com/ansible-collections/community.routeros/issues/372, https://github.com/ansible-collections/community.routeros/pull/373)." From 88806047e3dc600567f5cabfa6c470b95a920951 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 4 Jun 2025 15:19:28 +0200 Subject: [PATCH 338/365] Enable no-trailing-whitespace test. --- README.md | 2 +- antsibull-nox.toml | 4 ++++ docs/docsite/rst/api-guide.rst | 2 +- docs/docsite/rst/ssh-guide.rst | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59d2aa4..05e6c81 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, ## External requirements -The exact requirements for every module are listed in the module documentation. +The exact requirements for every module are listed in the module documentation. ### Supported connections diff --git a/antsibull-nox.toml b/antsibull-nox.toml index d95dfed..776e49f 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -30,6 +30,10 @@ run_no_unwanted_files = true no_unwanted_files_module_extensions = [".py"] no_unwanted_files_yaml_extensions = [".yml"] run_action_groups = true +run_no_trailing_whitespace = true +no_trailing_whitespace_skip_directories = [ + "tests/unit/plugins/modules/fixtures/", +] [[sessions.extra_checks.action_groups_config]] name = "api" diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index 6140d81..be4bfa3 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -57,7 +57,7 @@ This results in the following output: } PLAY RECAP ******************************************************************************************************* - localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 Check out the documentation of the :ansplugin:`community.routeros.api module ` for details on the options. diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index 4b0eb20..685038e 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -126,4 +126,4 @@ This results in the following output: } PLAY RECAP ******************************************************************************************************* - router : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 + router : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 From 49e4b83594765a42ca82e52d252e0a73d6bf6075 Mon Sep 17 00:00:00 2001 From: SdVSysAdmin Date: Fri, 13 Jun 2025 08:10:27 +0200 Subject: [PATCH 339/365] support for 'ip ipsec mode-config' (#376) * Added support for 'ip ipsec mode-config' * Create 376-ipsec-mode-config.yml --------- Co-authored-by: Laurent Papier --- .../fragments/376-ipsec-mode-config.yml | 3 +++ plugins/module_utils/_api_data.py | 19 ++++++++++++++----- plugins/modules/api_info.py | 1 + plugins/modules/api_modify.py | 1 + 4 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/376-ipsec-mode-config.yml diff --git a/changelogs/fragments/376-ipsec-mode-config.yml b/changelogs/fragments/376-ipsec-mode-config.yml new file mode 100644 index 0000000..27bad66 --- /dev/null +++ b/changelogs/fragments/376-ipsec-mode-config.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_modify, api_info - support API path ``ip ipsec mode-config`` + (https://github.com/ansible-collections/community.routeros/pull/376). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index e95d599..92816f9 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -652,13 +652,22 @@ PATHS = { ), ('ip', 'ipsec', 'mode-config'): APIData( unversioned=VersionedAPIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), + versioned_fields=[ + ([('6.43', '>=')], 'responder', KeyInfo(default=False)), + ([('6.44', '>=')], 'address', KeyInfo(can_disable=True, remove_value='0.0.0.0')), + ], fields={ - 'default': KeyInfo(), + 'address-pool': KeyInfo(can_disable=True, remove_value='none'), + 'address-prefix-length': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'name': KeyInfo(), - 'responder': KeyInfo(), - 'use-responder-dns': KeyInfo(), + 'split-dns': KeyInfo(can_disable=True, remove_value=''), + 'split-include': KeyInfo(can_disable=True, remove_value=''), + 'src-address-list': KeyInfo(can_disable=True, remove_value=''), + 'static-dns': KeyInfo(can_disable=True, remove_value=''), + 'system-dns': KeyInfo(default=False), }, ), ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index bd36955..d3f1b9e 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -148,6 +148,7 @@ options: - ip firewall service-port - ip hotspot service-port - ip ipsec identity + - ip ipsec mode-config - ip ipsec peer - ip ipsec policy - ip ipsec profile diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 2c1b012..e89b051 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -159,6 +159,7 @@ options: - ip firewall service-port - ip hotspot service-port - ip ipsec identity + - ip ipsec mode-config - ip ipsec peer - ip ipsec policy - ip ipsec profile From c7b2275f2c5b1ef85faa679127b6d62f162044ec Mon Sep 17 00:00:00 2001 From: Michael Jenny Date: Fri, 13 Jun 2025 08:10:37 +0200 Subject: [PATCH 340/365] Support RouterOS path /interface ethernet switch port-isolation and /routing bfd configuration (#375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update _api_data.py Add /interface/bridge property "port-cost-mode" which is supported since RouterOS 7.13. See changelog for details: https://mikrotik.com/download/changelogs * Create 371-add-bridge-port-cost-mode.yml * Update changelogs/fragments/371-add-bridge-port-cost-mode.yml Co-authored-by: Felix Fontein * Support for /interface ethernet switch port-isolation RouterOS has supported the /interface ethernet switch port-isolation path since version 6.43. This feature enables hardware offloaded Layer‑2 port isolation on supported switch chips Support for /routing bfd configuration Since RouterOS 7.11 it supports stable bfd support. See: https://iparchitechs.com/mikrotik-routeros-v7-11-stable-released/ * . * Add change file * attr order * Add name to fields * PEP8 * Update changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml Co-authored-by: Felix Fontein * Update changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein Co-authored-by: Michael Jenny --- ...solation-and-routing_bfd_configuration.yml | 6 ++++ plugins/module_utils/_api_data.py | 34 +++++++++++++++++++ plugins/modules/api_info.py | 2 ++ plugins/modules/api_modify.py | 2 ++ 4 files changed, 44 insertions(+) create mode 100644 changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml diff --git a/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml b/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml new file mode 100644 index 0000000..81d2976 --- /dev/null +++ b/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml @@ -0,0 +1,6 @@ +--- +minor_changes: + - api_info, api_modify - add ``interface ethernet switch port-isolation`` which is supported since RouterOS 6.43 (https://github.com/ansible-collections/community.routeros/pull/375). + - | + api_info, api_modify - add ``routing bfd configuration``. Officially stabilized BFD support for BGP and OSPF is available since RouterOS 7.11 + (https://github.com/ansible-collections/community.routeros/pull/375). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 92816f9..0fdb0ca 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4187,6 +4187,28 @@ PATHS = { }, ), ), + ('routing', 'bfd', 'configuration'): APIData( + versioned=[ + ('7.11', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'address-list': KeyInfo(), + 'addresses': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'copy-from': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'forbid-bfd': KeyInfo(), + 'interfaces': KeyInfo(), + 'min-echo-rx': KeyInfo(), + 'min-rx': KeyInfo(), + 'min-tx': KeyInfo(), + 'multiplier': KeyInfo(), + 'place-before': KeyInfo(), + 'vrf': KeyInfo(), + }, + )) + ], + ), ('routing', 'bfd', 'interface'): APIData( unversioned=VersionedAPIData( unknown_mechanism=True, @@ -4903,6 +4925,18 @@ PATHS = { }, ), ), + ('interface', 'ethernet', 'switch', 'port-isolation'): APIData( + versioned=[ + ('6.43', '>=', VersionedAPIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'forwarding-override': KeyInfo(), + 'name': KeyInfo(), + }, + )), + ], + ), ('ip', 'dhcp-client', 'option'): APIData( unversioned=VersionedAPIData( fixed_entries=True, diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index d3f1b9e..1eb8a94 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -68,6 +68,7 @@ options: - interface ethernet poe - interface ethernet switch - interface ethernet switch port + - interface ethernet switch port-isolation - interface gre - interface gre6 - interface l2tp-client @@ -203,6 +204,7 @@ options: - queue type - radius - radius incoming + - routing bfd configuration - routing bgp aggregate - routing bgp connection - routing bgp instance diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index e89b051..dfa6fd5 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -79,6 +79,7 @@ options: - interface ethernet poe - interface ethernet switch - interface ethernet switch port + - interface ethernet switch port-isolation - interface gre - interface gre6 - interface l2tp-client @@ -214,6 +215,7 @@ options: - queue type - radius - radius incoming + - routing bfd configuration - routing bgp aggregate - routing bgp connection - routing bgp instance From 4571d777dea8715b971be0b3eb7b453005e012fa Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 13 Jun 2025 08:11:36 +0200 Subject: [PATCH 341/365] Prepare 3.8.0. --- changelogs/fragments/3.8.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.8.0.yml diff --git a/changelogs/fragments/3.8.0.yml b/changelogs/fragments/3.8.0.yml new file mode 100644 index 0000000..512efc9 --- /dev/null +++ b/changelogs/fragments/3.8.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. diff --git a/galaxy.yml b/galaxy.yml index b9f4453..1966418 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.7.0 +version: 3.8.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From aa83116c7851e6231b3568f56999faba8d450398 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 14 Jun 2025 16:49:40 +0200 Subject: [PATCH 342/365] Release 3.8.0. --- CHANGELOG.md | 285 ++++++++++-------- CHANGELOG.rst | 16 + changelogs/changelog.yaml | 18 ++ changelogs/fragments/3.8.0.yml | 1 - ...solation-and-routing_bfd_configuration.yml | 6 - .../fragments/376-ipsec-mode-config.yml | 3 - 6 files changed, 186 insertions(+), 143 deletions(-) delete mode 100644 changelogs/fragments/3.8.0.yml delete mode 100644 changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml delete mode 100644 changelogs/fragments/376-ipsec-mode-config.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 294687e..248e59b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,153 +2,156 @@ **Topics** -- v3\.7\.0 +- v3\.8\.0 - Release Summary - Minor Changes -- v3\.6\.0 +- v3\.7\.0 - Release Summary - Minor Changes -- v3\.5\.0 +- v3\.6\.0 - Release Summary - Minor Changes -- v3\.4\.0 +- v3\.5\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes +- v3\.1\.0 + - Release Summary + - Minor Changes - Bugfixes - v3\.0\.0 - - Release Summary + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes +- v2\.18\.0 + - Release Summary + - Minor Changes - Deprecated Features - Bugfixes - v2\.17\.0 - - Release Summary - - Minor Changes -- v2\.16\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.9\.0 + - Release Summary + - Minor Changes - Bugfixes - v2\.8\.3 - - Release Summary + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.8\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.6\.0 + - Bugfixes +- v2\.7\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.5\.0 + - Bugfixes +- v2\.6\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.4\.0 + - Bugfixes +- v2\.5\.0 - Release Summary - Minor Changes + - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - v2\.2\.1 - - Release Summary + - Release Summary - Bugfixes - v2\.2\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Bugfixes - New Modules - v2\.0\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - Breaking Changes / Porting Guide - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 + - Bugfixes +- v1\.1\.0 - Release Summary + - Minor Changes +- v1\.0\.1 + - Release Summary - Bugfixes - v1\.0\.0 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.1 - - Release Summary + - Release Summary - Bugfixes - v0\.1\.0 - - Release Summary - - Minor Changes + - Release Summary + - Minor Changes - -## v3\.7\.0 + +## v3\.8\.0 ### Release Summary @@ -158,11 +161,13 @@ Feature release\. ### Minor Changes -* api\_find\_and\_modify \- allow to control whether dynamic and/or builtin entries are ignored with the new ignore\_dynamic and ignore\_builtin options \([https\://github\.com/ansible\-collections/community\.routeros/issues/372](https\://github\.com/ansible\-collections/community\.routeros/issues/372)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/373](https\://github\.com/ansible\-collections/community\.routeros/pull/373)\)\. -* api\_info\, api\_modify \- add port\-cost\-mode to interface bridge which is supported since RouterOS 7\.13 \([https\://github\.com/ansible\-collections/community\.routeros/pull/371](https\://github\.com/ansible\-collections/community\.routeros/pull/371)\)\. +* api\_info\, api\_modify \- add interface ethernet switch port\-isolation which is supported since RouterOS 6\.43 \([https\://github\.com/ansible\-collections/community\.routeros/pull/375](https\://github\.com/ansible\-collections/community\.routeros/pull/375)\)\. +* api\_info\, api\_modify \- add routing bfd configuration\. Officially stabilized BFD support for BGP and OSPF is available since RouterOS 7\.11 + \([https\://github\.com/ansible\-collections/community\.routeros/pull/375](https\://github\.com/ansible\-collections/community\.routeros/pull/375)\)\. +* api\_modify\, api\_info \- support API path ip ipsec mode\-config \([https\://github\.com/ansible\-collections/community\.routeros/pull/376](https\://github\.com/ansible\-collections/community\.routeros/pull/376)\)\. - -## v3\.6\.0 + +## v3\.7\.0 ### Release Summary @@ -172,12 +177,11 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. -* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. -* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. +* api\_find\_and\_modify \- allow to control whether dynamic and/or builtin entries are ignored with the new ignore\_dynamic and ignore\_builtin options \([https\://github\.com/ansible\-collections/community\.routeros/issues/372](https\://github\.com/ansible\-collections/community\.routeros/issues/372)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/373](https\://github\.com/ansible\-collections/community\.routeros/pull/373)\)\. +* api\_info\, api\_modify \- add port\-cost\-mode to interface bridge which is supported since RouterOS 7\.13 \([https\://github\.com/ansible\-collections/community\.routeros/pull/371](https\://github\.com/ansible\-collections/community\.routeros/pull/371)\)\. - -## v3\.5\.0 + +## v3\.6\.0 ### Release Summary @@ -187,17 +191,32 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. +* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. +* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. + + +## v3\.5\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- change default for /ip/cloud/ddns\-enabled for RouterOS 7\.17 and newer from yes to auto \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\. ## v3\.4\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. @@ -210,12 +229,12 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. @@ -226,12 +245,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -239,12 +258,12 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. @@ -257,7 +276,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -275,12 +294,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -291,12 +310,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -308,12 +327,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -337,12 +356,12 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. @@ -352,12 +371,12 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. @@ -366,12 +385,12 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. @@ -388,12 +407,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -403,12 +422,12 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. @@ -422,12 +441,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -441,12 +460,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -461,12 +480,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -498,12 +517,12 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. @@ -517,7 +536,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -538,7 +557,7 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - + ### Release Summary Bugfix release\. @@ -551,7 +570,7 @@ Bugfix release\. ## v2\.8\.1 - + ### Release Summary Bugfix release\. @@ -564,12 +583,12 @@ Bugfix release\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. @@ -589,12 +608,12 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -607,12 +626,12 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -627,12 +646,12 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -645,12 +664,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -689,7 +708,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -702,12 +721,12 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. @@ -722,7 +741,7 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. @@ -736,12 +755,12 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -760,12 +779,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -789,12 +808,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -830,12 +849,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -851,12 +870,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -865,7 +884,7 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. @@ -878,7 +897,7 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. @@ -891,7 +910,7 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. @@ -904,12 +923,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 627304d..cc72cad 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,22 @@ Community RouterOS Release Notes .. contents:: Topics +v3.8.0 +====== + +Release Summary +--------------- + +Feature release. + +Minor Changes +------------- + +- api_info, api_modify - add ``interface ethernet switch port-isolation`` which is supported since RouterOS 6.43 (https://github.com/ansible-collections/community.routeros/pull/375). +- api_info, api_modify - add ``routing bfd configuration``. Officially stabilized BFD support for BGP and OSPF is available since RouterOS 7.11 + (https://github.com/ansible-collections/community.routeros/pull/375). +- api_modify, api_info - support API path ``ip ipsec mode-config`` (https://github.com/ansible-collections/community.routeros/pull/376). + v3.7.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 3297286..eaaf93e 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -916,3 +916,21 @@ releases: - 371-add-bridge-port-cost-mode.yml - 373-api_find_and_modify-dynamic-builtin.yml release_date: '2025-05-31' + 3.8.0: + changes: + minor_changes: + - api_info, api_modify - add ``interface ethernet switch port-isolation`` + which is supported since RouterOS 6.43 (https://github.com/ansible-collections/community.routeros/pull/375). + - 'api_info, api_modify - add ``routing bfd configuration``. Officially stabilized + BFD support for BGP and OSPF is available since RouterOS 7.11 + + (https://github.com/ansible-collections/community.routeros/pull/375). + + ' + - api_modify, api_info - support API path ``ip ipsec mode-config`` (https://github.com/ansible-collections/community.routeros/pull/376). + release_summary: Feature release. + fragments: + - 3.8.0.yml + - 375-port_isolation-and-routing_bfd_configuration.yml + - 376-ipsec-mode-config.yml + release_date: '2025-06-14' diff --git a/changelogs/fragments/3.8.0.yml b/changelogs/fragments/3.8.0.yml deleted file mode 100644 index 512efc9..0000000 --- a/changelogs/fragments/3.8.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Feature release. diff --git a/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml b/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml deleted file mode 100644 index 81d2976..0000000 --- a/changelogs/fragments/375-port_isolation-and-routing_bfd_configuration.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -minor_changes: - - api_info, api_modify - add ``interface ethernet switch port-isolation`` which is supported since RouterOS 6.43 (https://github.com/ansible-collections/community.routeros/pull/375). - - | - api_info, api_modify - add ``routing bfd configuration``. Officially stabilized BFD support for BGP and OSPF is available since RouterOS 7.11 - (https://github.com/ansible-collections/community.routeros/pull/375). diff --git a/changelogs/fragments/376-ipsec-mode-config.yml b/changelogs/fragments/376-ipsec-mode-config.yml deleted file mode 100644 index 27bad66..0000000 --- a/changelogs/fragments/376-ipsec-mode-config.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_modify, api_info - support API path ``ip ipsec mode-config`` - (https://github.com/ansible-collections/community.routeros/pull/376). From b751d79a98ebd1bfce3d5bab3c797a9c2960fbd8 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 17 Jun 2025 07:19:14 +0200 Subject: [PATCH 343/365] Update yamllint config, fix YAML. --- .yamllint-extra-docs | 53 ++++++++++++++++++++++++++++++++++ antsibull-nox.toml | 1 + docs/docsite/rst/api-guide.rst | 2 +- docs/docsite/rst/ssh-guide.rst | 26 ++++++++--------- 4 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 .yamllint-extra-docs diff --git a/.yamllint-extra-docs b/.yamllint-extra-docs new file mode 100644 index 0000000..7e24c0f --- /dev/null +++ b/.yamllint-extra-docs @@ -0,0 +1,53 @@ +--- +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +# SPDX-FileCopyrightText: 2025 Felix Fontein + +extends: default + +ignore: | + /changelogs/ + +rules: + line-length: + max: 160 + level: error + document-start: disable + document-end: + present: false + truthy: + level: error + allowed-values: + - 'true' + - 'false' + indentation: + spaces: 2 + indent-sequences: true + key-duplicates: enable + trailing-spaces: enable + new-line-at-end-of-file: disable + hyphens: + max-spaces-after: 1 + empty-lines: + max: 2 + max-start: 0 + max-end: 0 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true + comments: + min-spaces-from-content: 1 + comments-indentation: false diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 776e49f..8391654 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -18,6 +18,7 @@ run_yamllint = true yamllint_config = ".yamllint" yamllint_config_plugins = ".yamllint-docs" yamllint_config_plugins_examples = ".yamllint-examples" +yamllint_config_extra_docs = ".yamllint-extra-docs" run_mypy = false [sessions.docs_check] diff --git a/docs/docsite/rst/api-guide.rst b/docs/docsite/rst/api-guide.rst index be4bfa3..9df17fc 100644 --- a/docs/docsite/rst/api-guide.rst +++ b/docs/docsite/rst/api-guide.rst @@ -191,7 +191,7 @@ When this playbook completed successfully, you should be able to use the HTTPS a .. code-block:: yaml+jinja - community.routeros.api: - ... + # ... tls: true validate_certs: true validate_cert_hostname: true diff --git a/docs/docsite/rst/ssh-guide.rst b/docs/docsite/rst/ssh-guide.rst index 685038e..ac1f65b 100644 --- a/docs/docsite/rst/ssh-guide.rst +++ b/docs/docsite/rst/ssh-guide.rst @@ -66,22 +66,22 @@ With the above inventory, you can use the following playbook to execute ``/syste gather_facts: false tasks: - - name: Gather system resources - community.routeros.command: - commands: - - /system resource print - register: system_resource_print + - name: Gather system resources + community.routeros.command: + commands: + - /system resource print + register: system_resource_print - - name: Show system resources - debug: - var: system_resource_print.stdout_lines + - name: Show system resources + debug: + var: system_resource_print.stdout_lines - - name: Gather facts - community.routeros.facts: + - name: Gather facts + community.routeros.facts: - - name: Show a fact - debug: - msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}" + - name: Show a fact + debug: + msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}" This results in the following output: From 6008397375b2916df045ea00ad4d7e51dbd1ebf1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 18 Jun 2025 21:48:53 +0200 Subject: [PATCH 344/365] Add linting check for RST code blocks. --- antsibull-nox.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 8391654..d82f63c 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -23,6 +23,15 @@ run_mypy = false [sessions.docs_check] validate_collection_refs="all" +codeblocks_restrict_types = [ + "ansible-output", + "ini", + "yaml", + "yaml+jinja", +] +codeblocks_restrict_type_exact_case = true +codeblocks_allow_without_type = false +codeblocks_allow_literal_blocks = false [sessions.license_check] From 3475751b30ba7ceefa0d4c0906cb7df085f90d79 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 1 Jul 2025 07:24:51 +0200 Subject: [PATCH 345/365] Add stable-2.19 to CI; add ignore-2.20.txt (#378) * Add ignore-2.20.txt. * Restrict stable-2.19 versions. --- antsibull-nox.toml | 1 + tests/sanity/ignore-2.20.txt | 1 + tests/sanity/ignore-2.20.txt.license | 3 +++ 3 files changed, 5 insertions(+) create mode 100644 tests/sanity/ignore-2.20.txt create mode 100644 tests/sanity/ignore-2.20.txt.license diff --git a/antsibull-nox.toml b/antsibull-nox.toml index d82f63c..6478f27 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -69,3 +69,4 @@ controller_python_versions_only = true "2.16" = ["3.10"] "2.17" = ["3.8"] "2.18" = ["3.9"] +"2.19" = ["3.11"] diff --git a/tests/sanity/ignore-2.20.txt b/tests/sanity/ignore-2.20.txt new file mode 100644 index 0000000..65e5bca --- /dev/null +++ b/tests/sanity/ignore-2.20.txt @@ -0,0 +1 @@ +tests/update-docs.py shebang diff --git a/tests/sanity/ignore-2.20.txt.license b/tests/sanity/ignore-2.20.txt.license new file mode 100644 index 0000000..edff8c7 --- /dev/null +++ b/tests/sanity/ignore-2.20.txt.license @@ -0,0 +1,3 @@ +GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +SPDX-License-Identifier: GPL-3.0-or-later +SPDX-FileCopyrightText: Ansible Project From d9be02bdb8ab0e92459627b0197314fd5e77f47c Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 1 Jul 2025 22:34:37 +0200 Subject: [PATCH 346/365] Adjust README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05e6c81..7d4f4c3 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ For more information about communication, see the [Ansible communication guide]( ## Tested with Ansible -Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, and ansible-core 2.18 releases and the current development version of ansible-core. Ansible 2.9, ansible-base 2.10, and ansible-core versions before 2.15.0 are not supported. +Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, ansible-core 2.18, and ansible-core 2.19 releases and the current development version of ansible-core. Ansible 2.9, ansible-base 2.10, and ansible-core versions before 2.15.0 are not supported. ## External requirements From bb7eadbc9ffb78e946dae745d4057cf022a627b5 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 6 Jul 2025 18:05:28 +0200 Subject: [PATCH 347/365] Avoid tabs. --- antsibull-nox.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 6478f27..082b06c 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -44,6 +44,7 @@ run_no_trailing_whitespace = true no_trailing_whitespace_skip_directories = [ "tests/unit/plugins/modules/fixtures/", ] +run_avoid_characters = true [[sessions.extra_checks.action_groups_config]] name = "api" @@ -51,6 +52,10 @@ pattern = "^api.*$" exclusions = [] doc_fragment = "community.routeros.attributes.actiongroup_api" +[[sessions.extra_checks.avoid_character_group]] +name = "tab" +regex = "\\x09" + [sessions.build_import_check] run_galaxy_importer = true From 852e21a2f2cb2888f61a5addb2682b57c969cd56 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 25 Jul 2025 18:59:28 +0200 Subject: [PATCH 348/365] Move EE tests to antsibull-nox. (#384) --- .github/workflows/ee.yml | 159 --------------------------------------- antsibull-nox.toml | 20 +++++ 2 files changed, 20 insertions(+), 159 deletions(-) delete mode 100644 .github/workflows/ee.yml diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml deleted file mode 100644 index 5b45972..0000000 --- a/.github/workflows/ee.yml +++ /dev/null @@ -1,159 +0,0 @@ ---- -# Copyright (c) Ansible Project -# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) -# SPDX-License-Identifier: GPL-3.0-or-later - -name: execution environment -'on': - # Run CI against all pushes (direct commits, also merged PRs), Pull Requests - push: - branches: - - main - - stable-* - pull_request: - # Run CI once per day (at 05:15 UTC) - # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-builder - schedule: - - cron: '15 5 * * *' - -env: - NAMESPACE: community - COLLECTION_NAME: routeros - -jobs: - build: - name: Build and test EE (${{ matrix.name }}) - strategy: - fail-fast: false - matrix: - name: - - '' - ansible_core: - - '' - ansible_runner: - - '' - base_image: - - '' - pre_base: - - '' - extra_vars: - - '' - other_deps: - - '' - exclude: - - ansible_core: '' - include: - - name: ansible-core devel @ RHEL UBI 9 - ansible_core: https://github.com/ansible/ansible/archive/devel.tar.gz - ansible_runner: ansible-runner - other_deps: |2 - python_interpreter: - package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography - python_path: "/usr/bin/python3.11" - base_image: docker.io/redhat/ubi9:latest - pre_base: '"#"' - - name: ansible-core 2.15 @ Rocky Linux 9 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz - ansible_runner: ansible-runner - base_image: quay.io/rockylinux/rockylinux:9 - pre_base: '"#"' - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v4 - with: - path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - persist-credentials: false - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install ansible-builder and ansible-navigator - run: pip install ansible-builder ansible-navigator - - - name: Verify requirements - run: ansible-builder introspect --sanitize . - - - name: Make sure galaxy.yml has version entry - run: >- - python -c - 'import yaml ; - f = open("galaxy.yml", "rb") ; - data = yaml.safe_load(f) ; - f.close() ; - data["version"] = data.get("version") or "0.0.1" ; - f = open("galaxy.yml", "wb") ; - f.write(yaml.dump(data).encode("utf-8")) ; - f.close() ; - ' - working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - - - name: Build collection - run: | - ansible-galaxy collection build --output-path ../../../ - working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - - - name: Create files for building execution environment - run: | - COLLECTION_FILENAME="$(ls "${NAMESPACE}-${COLLECTION_NAME}"-*.tar.gz)" - - # EE config - cat > execution-environment.yml < requirements.yml < - ansible-navigator run - --mode stdout - --container-engine docker - --pull-policy never - --set-environment-variable ANSIBLE_PRIVATE_ROLE_VARS=true - --execution-environment-image test-ee:latest - -v - all.yml - ${{ matrix.extra_vars }} - working-directory: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}/tests/ee diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 082b06c..885e041 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -75,3 +75,23 @@ controller_python_versions_only = true "2.17" = ["3.8"] "2.18" = ["3.9"] "2.19" = ["3.11"] + +[[sessions.ee_check.execution_environments]] +name = "devel-ubi-9" +description = "ansible-core devel @ RHEL UBI 9" +test_playbooks = ["tests/ee/all.yml"] +config.images.base_image.name = "docker.io/redhat/ubi9:latest" +config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/devel.tar.gz" +config.dependencies.ansible_runner.package_pip = "ansible-runner" +config.dependencies.python_interpreter.package_system = "python3.11 python3.11-pip python3.11-wheel python3.11-cryptography" +config.dependencies.python_interpreter.python_path = "/usr/bin/python3.11" +runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"} + +[[sessions.ee_check.execution_environments]] +name = "2.15-rocky-9" +description = "ansible-core 2.15 @ Rocky Linux 9" +test_playbooks = ["tests/ee/all.yml"] +config.images.base_image.name = "quay.io/rockylinux/rockylinux:9" +config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/stable-2.15.tar.gz" +config.dependencies.ansible_runner.package_pip = "ansible-runner" +runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"} From 9099fcd6987c895b41a9564813bf01dabae66120 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 25 Jul 2025 22:19:29 +0200 Subject: [PATCH 349/365] Prepare 3.8.1. --- changelogs/fragments/3.8.1.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.8.1.yml diff --git a/changelogs/fragments/3.8.1.yml b/changelogs/fragments/3.8.1.yml new file mode 100644 index 0000000..8ce9aa9 --- /dev/null +++ b/changelogs/fragments/3.8.1.yml @@ -0,0 +1 @@ +release_summary: Bugfix release. diff --git a/galaxy.yml b/galaxy.yml index 1966418..31eb214 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.8.0 +version: 3.8.1 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 1c182725ce8f5020c53cdf07a271beb3010c3140 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 25 Jul 2025 22:26:39 +0200 Subject: [PATCH 350/365] Prevent deprecation warnings when using ansible-core 2.19. (#385) --- changelogs/fragments/384-warnings.yml | 2 ++ plugins/modules/api_facts.py | 4 +--- plugins/modules/facts.py | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/384-warnings.yml diff --git a/changelogs/fragments/384-warnings.yml b/changelogs/fragments/384-warnings.yml new file mode 100644 index 0000000..77eaef9 --- /dev/null +++ b/changelogs/fragments/384-warnings.yml @@ -0,0 +1,2 @@ +bugfixes: + - "facts and api_facts modules - prevent deprecation warnings when used with ansible-core 2.19 (https://github.com/ansible-collections/community.routeros/pull/384)." diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 41c9a4e..09c0fbb 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -419,8 +419,6 @@ FACT_SUBSETS = dict( VALID_SUBSETS = frozenset(FACT_SUBSETS.keys()) -warnings = [] - def main(): argument_spec = dict( @@ -485,7 +483,7 @@ def main(): key = 'ansible_net_%s' % key ansible_facts[key] = value - module.exit_json(ansible_facts=ansible_facts, warnings=warnings) + module.exit_json(ansible_facts=ansible_facts) if __name__ == '__main__': diff --git a/plugins/modules/facts.py b/plugins/modules/facts.py index e75d609..e80143c 100644 --- a/plugins/modules/facts.py +++ b/plugins/modules/facts.py @@ -589,8 +589,6 @@ FACT_SUBSETS = dict( VALID_SUBSETS = frozenset(FACT_SUBSETS.keys()) -warnings = list() - def main(): """main entry point for module execution @@ -653,7 +651,7 @@ def main(): key = 'ansible_net_%s' % key ansible_facts[key] = value - module.exit_json(ansible_facts=ansible_facts, warnings=warnings) + module.exit_json(ansible_facts=ansible_facts) if __name__ == '__main__': From 6e9d2e137969a13d08db354bdf145adeba77aaa6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 26 Jul 2025 14:38:22 +0200 Subject: [PATCH 351/365] Release 3.8.1. --- CHANGELOG.md | 290 ++++++++++++++------------ CHANGELOG.rst | 13 ++ changelogs/changelog.yaml | 10 + changelogs/fragments/3.8.1.yml | 1 - changelogs/fragments/384-warnings.yml | 2 - 5 files changed, 176 insertions(+), 140 deletions(-) delete mode 100644 changelogs/fragments/3.8.1.yml delete mode 100644 changelogs/fragments/384-warnings.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 248e59b..88a7efe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,158 +2,174 @@ **Topics** -- v3\.8\.0 +- v3\.8\.1 - Release Summary + - Bugfixes +- v3\.8\.0 + - Release Summary - Minor Changes - v3\.7\.0 - - Release Summary + - Release Summary - Minor Changes - v3\.6\.0 - - Release Summary + - Release Summary - Minor Changes - v3\.5\.0 - - Release Summary + - Release Summary - Minor Changes - v3\.4\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v3\.3\.0 - Release Summary + - Minor Changes + - Bugfixes +- v3\.3\.0 + - Release Summary - Minor Changes - v3\.2\.0 - - Release Summary + - Release Summary - Minor Changes - v3\.1\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v3\.0\.0 - Release Summary + - Minor Changes + - Bugfixes +- v3\.0\.0 + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.19\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.18\.0 - - Release Summary + - Release Summary - Minor Changes - Deprecated Features - - Bugfixes + - Bugfixes - v2\.17\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.16\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.15\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.14\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.13\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.12\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.12\.0 + - Release Summary - Minor Changes - v2\.11\.0 - - Release Summary + - Release Summary - Minor Changes - v2\.10\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.9\.0 - Release Summary - - Minor Changes + - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - - Minor Changes + - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - - Minor Changes + - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - - Minor Changes + - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - - Minor Changes + - Minor Changes - Bugfixes +- v2\.4\.0 + - Release Summary + - Minor Changes + - Bugfixes - Known Issues - v2\.3\.1 - - Release Summary + - Release Summary - Known Issues - v2\.3\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v2\.2\.1 - Release Summary + - Minor Changes - Bugfixes -- v2\.2\.0 +- v2\.2\.1 - Release Summary - - Minor Changes - Bugfixes +- v2\.2\.0 + - Release Summary + - Minor Changes + - Bugfixes - New Modules - v2\.1\.0 - - Release Summary + - Release Summary - Minor Changes - - Bugfixes + - Bugfixes - New Modules - v2\.0\.0 - - Release Summary + - Release Summary - Minor Changes - Breaking Changes / Porting Guide - - Bugfixes + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary + - Minor Changes + - Bugfixes +- v1\.1\.0 + - Release Summary - Minor Changes - v1\.0\.1 - - Release Summary - - Bugfixes -- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary + - Bugfixes +- v0\.1\.0 + - Release Summary - Minor Changes + +## v3\.8\.1 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + +* facts and api\_facts modules \- prevent deprecation warnings when used with ansible\-core 2\.19 \([https\://github\.com/ansible\-collections/community\.routeros/pull/384](https\://github\.com/ansible\-collections/community\.routeros/pull/384)\)\. + ## v3\.8\.0 - + ### Release Summary Feature release\. @@ -169,7 +185,7 @@ Feature release\. ## v3\.7\.0 - + ### Release Summary Feature release\. @@ -183,7 +199,7 @@ Feature release\. ## v3\.6\.0 - + ### Release Summary Feature release\. @@ -198,7 +214,7 @@ Feature release\. ## v3\.5\.0 - + ### Release Summary Feature release\. @@ -211,7 +227,7 @@ Feature release\. ## v3\.4\.0 - + ### Release Summary Feature and bugfix release\. @@ -221,7 +237,7 @@ Feature and bugfix release\. * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. - + ### Bugfixes * api\_info\, api\_modify \- remove the primary key action from the interface wifi provisioning path\, since RouterOS also allows to create completely duplicate entries \([https\://github\.com/ansible\-collections/community\.routeros/issues/344](https\://github\.com/ansible\-collections/community\.routeros/issues/344)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/345](https\://github\.com/ansible\-collections/community\.routeros/pull/345)\)\. @@ -229,7 +245,7 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. @@ -245,7 +261,7 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. @@ -258,7 +274,7 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. @@ -268,7 +284,7 @@ Bugfix and feature release\. * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. - + ### Bugfixes * api\_info\, api\_modify \- fields log and log\-prefix in paths ip firewall filter\, ip firewall mangle\, ip firewall nat\, ip firewall raw now have the correct default values \([https\://github\.com/ansible\-collections/community\.routeros/pull/324](https\://github\.com/ansible\-collections/community\.routeros/pull/324)\)\. @@ -276,7 +292,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -294,7 +310,7 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. @@ -310,7 +326,7 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. @@ -327,7 +343,7 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. @@ -348,7 +364,7 @@ Feature release\. * The collection deprecates support for all Ansible/ansible\-base/ansible\-core versions that are currently End of Life\, [according to the ansible\-core support matrix](https\://docs\.ansible\.com/ansible\-core/devel/reference\_appendices/release\_and\_maintenance\.html\#ansible\-core\-support\-matrix)\. This means that the next major release of the collection will no longer support Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. - + ### Bugfixes * api\_modify\, api\_info \- change the default of ingress\-filtering in paths interface bridge and interface bridge port back to false for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -356,7 +372,7 @@ Feature release\. ## v2\.17\.0 - + ### Release Summary Feature release\. @@ -371,7 +387,7 @@ Feature release\. ## v2\.16\.0 - + ### Release Summary Feature release\. @@ -385,7 +401,7 @@ Feature release\. ## v2\.15\.0 - + ### Release Summary Feature release\. @@ -407,7 +423,7 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. @@ -422,7 +438,7 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. @@ -433,7 +449,7 @@ Bugfix and feature release\. * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + ### Bugfixes * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. @@ -441,7 +457,7 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. @@ -460,7 +476,7 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. @@ -480,7 +496,7 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. @@ -509,7 +525,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -517,7 +533,7 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. @@ -528,7 +544,7 @@ Bugfix and feature release\. * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -536,7 +552,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -557,19 +573,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -578,12 +581,25 @@ Bugfix release\. ### Bugfixes +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. + + +## v2\.8\.1 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + * facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. ## v2\.8\.0 - + ### Release Summary Bugfix and feature release\. @@ -598,7 +614,7 @@ Bugfix and feature release\. * api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. * command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. - + ### Bugfixes * api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. @@ -608,7 +624,7 @@ Bugfix and feature release\. ## v2\.7\.0 - + ### Release Summary Bugfix and feature release\. @@ -618,7 +634,7 @@ Bugfix and feature release\. * api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. - + ### Bugfixes * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. @@ -626,7 +642,7 @@ Bugfix and feature release\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. @@ -637,7 +653,7 @@ Regular bugfix and feature release\. * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -646,7 +662,7 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. @@ -656,7 +672,7 @@ Feature and bugfix release\. * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -664,7 +680,7 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. @@ -690,7 +706,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -708,7 +724,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -721,7 +737,7 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. @@ -733,7 +749,7 @@ Feature and bugfix release\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -741,12 +757,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -755,7 +771,7 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. @@ -765,7 +781,7 @@ New feature release\. * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -779,7 +795,7 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. @@ -793,7 +809,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -808,7 +824,7 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. @@ -827,7 +843,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -849,7 +865,7 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. @@ -862,7 +878,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -870,7 +886,7 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. @@ -884,12 +900,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -897,12 +913,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -910,12 +926,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -923,7 +939,7 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cc72cad..2e73ef4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,19 @@ Community RouterOS Release Notes .. contents:: Topics +v3.8.1 +====== + +Release Summary +--------------- + +Bugfix release. + +Bugfixes +-------- + +- facts and api_facts modules - prevent deprecation warnings when used with ansible-core 2.19 (https://github.com/ansible-collections/community.routeros/pull/384). + v3.8.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index eaaf93e..df9d0e0 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -934,3 +934,13 @@ releases: - 375-port_isolation-and-routing_bfd_configuration.yml - 376-ipsec-mode-config.yml release_date: '2025-06-14' + 3.8.1: + changes: + bugfixes: + - facts and api_facts modules - prevent deprecation warnings when used with + ansible-core 2.19 (https://github.com/ansible-collections/community.routeros/pull/384). + release_summary: Bugfix release. + fragments: + - 3.8.1.yml + - 384-warnings.yml + release_date: '2025-07-26' diff --git a/changelogs/fragments/3.8.1.yml b/changelogs/fragments/3.8.1.yml deleted file mode 100644 index 8ce9aa9..0000000 --- a/changelogs/fragments/3.8.1.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix release. diff --git a/changelogs/fragments/384-warnings.yml b/changelogs/fragments/384-warnings.yml deleted file mode 100644 index 77eaef9..0000000 --- a/changelogs/fragments/384-warnings.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "facts and api_facts modules - prevent deprecation warnings when used with ansible-core 2.19 (https://github.com/ansible-collections/community.routeros/pull/384)." From e988b18acf4f903d5eb052a318a705d18a816f59 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 27 Jul 2025 16:35:29 +0200 Subject: [PATCH 352/365] Normalize changelog configs. --- changelogs/config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelogs/config.yaml b/changelogs/config.yaml index a02e530..39b7120 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -7,9 +7,9 @@ changelog_filename_template: ../CHANGELOG.rst changelog_filename_version_depth: 0 changes_file: changelog.yaml changes_format: combined +ignore_other_fragment_extensions: true keep_fragments: false mention_ancestor: true -flatmap: true new_plugins_after_name: removed_features notesdir: fragments output_formats: @@ -40,3 +40,4 @@ use_fqcn: true add_plugin_period: true changelog_nice_yaml: true changelog_sort: version +vcs: auto From 1f38be9e562dee377083aa86ca6a1d596742da48 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 28 Jul 2025 22:33:11 +0200 Subject: [PATCH 353/365] Update IPv6 settings fields for RouterOS 7.17/7.18 (#380) From the RouterOS 7.17 changelog: *) ipv6 - added IPv6 settings related to stale IPv6 neighbor cleanup; *) ipv6 - added support for manual link-local address configuration; And from the RouterOS 7.18 changelog: *) ipv6 - added FastTrack support; *) ipv6 - added support for neighbor removal and static entries; The change also removes the default value for the `max-neighbor-entries` field. It's documented to vary depending on the RAM size. --- changelogs/fragments/380-ipv6-settings.yml | 3 +++ plugins/module_utils/_api_data.py | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/380-ipv6-settings.yml diff --git a/changelogs/fragments/380-ipv6-settings.yml b/changelogs/fragments/380-ipv6-settings.yml new file mode 100644 index 0000000..a8c6e9b --- /dev/null +++ b/changelogs/fragments/380-ipv6-settings.yml @@ -0,0 +1,3 @@ +minor_changes: + - api_info, api_modify - add ``disable-link-local-address`` and ``stale-neighbor-timeout`` fields to ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/380). + - api_info, api_modify - adjust neighbor limit fields in ``ipv6 settings`` to match RouterOS 7.18 and newer (https://github.com/ansible-collections/community.routeros/pull/380). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 0fdb0ca..cf8aed8 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1553,13 +1553,19 @@ PATHS = { fully_understood=True, versioned_fields=[ ([('7.16', '>=')], 'multipath-hash-policy', KeyInfo(default='l3')), + ([('7.17', '>=')], 'disable-link-local-address', KeyInfo(default=False)), + ([('7.17', '>=')], 'stale-neighbor-timeout', KeyInfo(default=60)), + ([('7.18', '>=')], 'allow-fast-path', KeyInfo(default=True)), + ([('7.18', '<')], 'max-neighbor-entries', KeyInfo(default=8192)), + ([('7.18', '>=')], 'min-neighbor-entries', KeyInfo()), + ([('7.18', '>=')], 'soft-max-neighbor-entries', KeyInfo()), + ([('7.18', '>=')], 'max-neighbor-entries', KeyInfo()), ], fields={ 'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'), 'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'), 'disable-ipv6': KeyInfo(default=False), 'forward': KeyInfo(default=True), - 'max-neighbor-entries': KeyInfo(default=8192), }, ), ), From b70b4a72b3d810bd41c70e79c816833e0d112f05 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 28 Jul 2025 22:33:24 +0200 Subject: [PATCH 354/365] Set mangle passthrough default for RouterOS 7.19 (#382) The behaviour of the `passthrough` property in `ip/firewall/mangle` has changed in RouterOS 7.19: ``` *) firewall - always show "passthrough" when exporting mangle table; ``` Per the documentation at [1] the default is `true`. [1] https://help.mikrotik.com/docs/spaces/ROS/pages/48660587/Mangle --- changelogs/fragments/382-mangle-passthrough.yml | 2 ++ plugins/module_utils/_api_data.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/382-mangle-passthrough.yml diff --git a/changelogs/fragments/382-mangle-passthrough.yml b/changelogs/fragments/382-mangle-passthrough.yml new file mode 100644 index 0000000..2123dfa --- /dev/null +++ b/changelogs/fragments/382-mangle-passthrough.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - set ``passthrough`` default in ``ip firewall mangle`` to ``true`` for RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/382). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index cf8aed8..ceef7e4 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -3151,6 +3151,10 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, stratify_keys=('chain', ), + versioned_fields=[ + ([('7.19', '<')], 'passthrough', KeyInfo(can_disable=True)), + ([('7.19', '>=')], 'passthrough', KeyInfo(default=True)), + ], fields={ 'action': KeyInfo(), 'address-list': KeyInfo(can_disable=True), @@ -3202,7 +3206,6 @@ PATHS = { 'p2p': KeyInfo(can_disable=True), 'packet-mark': KeyInfo(can_disable=True), 'packet-size': KeyInfo(can_disable=True), - 'passthrough': KeyInfo(can_disable=True), 'per-connection-classifier': KeyInfo(can_disable=True), 'port': KeyInfo(can_disable=True), 'priority': KeyInfo(can_disable=True), From 008b5f893a2206302a07fb57ac64edcea53da406 Mon Sep 17 00:00:00 2001 From: Tr4sK Date: Mon, 28 Jul 2025 22:33:40 +0200 Subject: [PATCH 355/365] Update logging action fields for ROS 7.18 (#381) * Update logging action fields for ROS 7.18 * Add changelog fragment * Update changelogs/fragments/381-logging-cef.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- changelogs/fragments/381-logging-cef.yml | 2 ++ plugins/module_utils/_api_data.py | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 changelogs/fragments/381-logging-cef.yml diff --git a/changelogs/fragments/381-logging-cef.yml b/changelogs/fragments/381-logging-cef.yml new file mode 100644 index 0000000..849f82a --- /dev/null +++ b/changelogs/fragments/381-logging-cef.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api modify - add ``remote-log-format``, ``remote-protocol``, and ``event-delimiter`` to ``system logging action`` (https://github.com/ansible-collections/community.routeros/pull/381). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ceef7e4..10505f3 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -5221,6 +5221,11 @@ PATHS = { unversioned=VersionedAPIData( fully_understood=True, primary_keys=('name',), + versioned_fields=[ + ([('7.18', '>=')], 'remote-log-format', KeyInfo(default='default')), + ([('7.18', '>=')], 'remote-protocol', KeyInfo(default='udp')), + ([('7.18', '>=')], 'cef-event-delimiter', KeyInfo(default='\r\n')), + ], fields={ 'bsd-syslog': KeyInfo(default=False), 'comment': KeyInfo(can_disable=True, remove_value=''), From c9d15bc43a2e7fb06d80a11b4ce1941fd3a44cef Mon Sep 17 00:00:00 2001 From: Michael Jenny Date: Mon, 28 Jul 2025 22:34:15 +0200 Subject: [PATCH 356/365] OVPN server accepts now multiple items (RouterOS >= 7.17) (#383) * Since RouterOS 7.17 VRF is supported for OVPN server. It now supports multiple entries and single-value is now obsolete. This demands for a versioned API. * Add change fragment * Add change fragment * add license field * Update changelogs/fragments/385-vrf-support-for-ovpn-server Co-authored-by: Felix Fontein * rename * remove license field --------- Co-authored-by: Felix Fontein --- .../385-vrf-support-for-ovpn-server.yml | 7 +++ plugins/module_utils/_api_data.py | 57 +++++++++++++------ 2 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 changelogs/fragments/385-vrf-support-for-ovpn-server.yml diff --git a/changelogs/fragments/385-vrf-support-for-ovpn-server.yml b/changelogs/fragments/385-vrf-support-for-ovpn-server.yml new file mode 100644 index 0000000..4790a9d --- /dev/null +++ b/changelogs/fragments/385-vrf-support-for-ovpn-server.yml @@ -0,0 +1,7 @@ +--- +minor_changes: + - api_info, api_modify - since RouterOS 7.17 VRF is supported for OVPN server. + It now supports multiple entries, while ``api_modify`` so far only accepted a single entry. + The ``interface ovpn-server server`` path now allows multiple entries + on RouterOS 7.17 and newer + (https://github.com/ansible-collections/community.routeros/pull/383). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 10505f3..2b44b8b 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -1664,23 +1664,46 @@ PATHS = { ), ), ('interface', 'ovpn-server', 'server'): APIData( - unversioned=VersionedAPIData( - single_value=True, - fully_understood=True, - fields={ - 'auth': KeyInfo(), - 'cipher': KeyInfo(), - 'default-profile': KeyInfo(default='default'), - 'enabled': KeyInfo(default=False), - 'keepalive-timeout': KeyInfo(default=60), - 'mac-address': KeyInfo(), - 'max-mtu': KeyInfo(default=1500), - 'mode': KeyInfo(default='ip'), - 'netmask': KeyInfo(default=24), - 'port': KeyInfo(default=1194), - 'require-client-certificate': KeyInfo(default=False), - }, - ), + versioned=[ + ('7.17', '>=', VersionedAPIData( + fully_understood=True, + fields={ + 'auth': KeyInfo(), + 'cipher': KeyInfo(), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'mac-address': KeyInfo(), + 'max-mtu': KeyInfo(default=1500), + 'mode': KeyInfo(default='ip'), + 'name': KeyInfo(default=''), + 'netmask': KeyInfo(default=24), + 'port': KeyInfo(default=1194), + 'protocol': KeyInfo(default='tcp'), + 'require-client-certificate': KeyInfo(default=False), + 'vrf': KeyInfo(default='main'), + }, + )), + ('7.17', '<', VersionedAPIData( + single_value=True, + fully_understood=True, + fields={ + 'auth': KeyInfo(), + 'cipher': KeyInfo(), + 'default-profile': KeyInfo(default='default'), + 'enabled': KeyInfo(default=False), + 'keepalive-timeout': KeyInfo(default=60), + 'mac-address': KeyInfo(), + 'max-mtu': KeyInfo(default=1500), + 'mode': KeyInfo(default='ip'), + 'name': KeyInfo(default=''), + 'netmask': KeyInfo(default=24), + 'port': KeyInfo(default=1194), + 'protocol': KeyInfo(default='tcp'), + 'require-client-certificate': KeyInfo(default=False), + }, + )) + ] ), ('interface', 'pppoe-server', 'server'): APIData( unversioned=VersionedAPIData( From e78df4a4cff2bb097e4d10724376c69dd542773f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 28 Jul 2025 22:35:44 +0200 Subject: [PATCH 357/365] Prepare 3.9.0. --- changelogs/fragments/3.9.0.yml | 1 + galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/3.9.0.yml diff --git a/changelogs/fragments/3.9.0.yml b/changelogs/fragments/3.9.0.yml new file mode 100644 index 0000000..63e0654 --- /dev/null +++ b/changelogs/fragments/3.9.0.yml @@ -0,0 +1 @@ +release_summary: Feature release. \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 31eb214..f2ba31a 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -7,7 +7,7 @@ namespace: community name: routeros -version: 3.8.1 +version: 3.9.0 readme: README.md authors: - Egor Zaitsev (github.com/heuels) From 8edc8018a72fac41028c7024e6dc2564a0f972e1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 31 Jul 2025 07:18:42 +0200 Subject: [PATCH 358/365] Ansible-core devel EE: use Python 3.12. (#387) --- antsibull-nox.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antsibull-nox.toml b/antsibull-nox.toml index 885e041..72982fa 100644 --- a/antsibull-nox.toml +++ b/antsibull-nox.toml @@ -83,8 +83,8 @@ test_playbooks = ["tests/ee/all.yml"] config.images.base_image.name = "docker.io/redhat/ubi9:latest" config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/devel.tar.gz" config.dependencies.ansible_runner.package_pip = "ansible-runner" -config.dependencies.python_interpreter.package_system = "python3.11 python3.11-pip python3.11-wheel python3.11-cryptography" -config.dependencies.python_interpreter.python_path = "/usr/bin/python3.11" +config.dependencies.python_interpreter.package_system = "python3.12 python3.12-pip python3.12-wheel python3.12-cryptography" +config.dependencies.python_interpreter.python_path = "/usr/bin/python3.12" runtime_environment = {"ANSIBLE_PRIVATE_ROLE_VARS" = "true"} [[sessions.ee_check.execution_environments]] From 7395011b0c6054aa5c183511ede5d52cd079fb81 Mon Sep 17 00:00:00 2001 From: Jefferson Raylan Date: Thu, 31 Jul 2025 17:02:47 -0300 Subject: [PATCH 359/365] fix: Fix pattern to handle long system identity (#386) * fix: Fix pattern to handle long system identity names When the system identity string is too long, the terminal output may be truncated. The truncated output is marked by multiple carriage returns (`\r`) and a `<` symbol. This is a example of a truncated output: `\r\n\r\r\r\r ` The existing regex failed to match these truncated prompts. This update introduces a more flexible regex that matches both, the truncated and the preserved output. * add change-log fragment for pr 386 * refactoring change-log fragment for pr 386 * Update changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml Co-authored-by: Felix Fontein --------- Co-authored-by: Felix Fontein --- .../fragments/386-fix-pattern-to-handle-long-identity.yml | 3 +++ plugins/terminal/routeros.py | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml diff --git a/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml b/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml new file mode 100644 index 0000000..b9a749f --- /dev/null +++ b/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - routeros terminal plugin - fix ``terminal_stdout_re`` pattern to handle long system identities when connecting to RouterOS through SSH (https://github.com/ansible-collections/community.routeros/pull/386). diff --git a/plugins/terminal/routeros.py b/plugins/terminal/routeros.py index 9d50fa2..8a39561 100644 --- a/plugins/terminal/routeros.py +++ b/plugins/terminal/routeros.py @@ -31,7 +31,9 @@ class TerminalModule(TerminalBase): terminal_stdout_re = [ re.compile(br"\x1b<"), - re.compile(br"\[[\w\-\.]+\@[\w\s\-\.\/]+\] ?( ?$"), + re.compile( + br"((\[[\w\-\.]+\@)|(\r\<(([\w\-\.]*\@)|)))" + br"[\w\s\-\.\/]+\] ?( ?$"), re.compile(br"Please press \"Enter\" to continue!"), re.compile(br"Do you want to see the software license\? \[Y\/n\]: ?"), ] From e301f822d715df3d50429c7ace2a3bcaf0e19d33 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 10 Aug 2025 17:29:56 +0200 Subject: [PATCH 360/365] Update release summary. --- changelogs/fragments/3.9.0.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/3.9.0.yml b/changelogs/fragments/3.9.0.yml index 63e0654..56de6d9 100644 --- a/changelogs/fragments/3.9.0.yml +++ b/changelogs/fragments/3.9.0.yml @@ -1 +1 @@ -release_summary: Feature release. \ No newline at end of file +release_summary: Bugfix and feature release. From e40a3b011cc8cb194005a0a6b98bfb424d798ad1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 10 Aug 2025 17:34:56 +0200 Subject: [PATCH 361/365] Release 3.9.0. --- CHANGELOG.md | 450 +++++++++--------- CHANGELOG.rst | 22 + changelogs/changelog.yaml | 27 ++ changelogs/fragments/3.9.0.yml | 1 - changelogs/fragments/380-ipv6-settings.yml | 3 - changelogs/fragments/381-logging-cef.yml | 2 - .../fragments/382-mangle-passthrough.yml | 2 - .../385-vrf-support-for-ovpn-server.yml | 7 - ...86-fix-pattern-to-handle-long-identity.yml | 3 - 9 files changed, 287 insertions(+), 230 deletions(-) delete mode 100644 changelogs/fragments/3.9.0.yml delete mode 100644 changelogs/fragments/380-ipv6-settings.yml delete mode 100644 changelogs/fragments/381-logging-cef.yml delete mode 100644 changelogs/fragments/382-mangle-passthrough.yml delete mode 100644 changelogs/fragments/385-vrf-support-for-ovpn-server.yml delete mode 100644 changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 88a7efe..af8c632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,179 +2,205 @@ **Topics** -- v3\.8\.1 +- v3\.9\.0 - Release Summary - - Bugfixes -- v3\.8\.0 - - Release Summary - Minor Changes -- v3\.7\.0 + - Bugfixes +- v3\.8\.1 + - Release Summary + - Bugfixes +- v3\.8\.0 - Release Summary - Minor Changes -- v3\.6\.0 +- v3\.7\.0 - Release Summary - Minor Changes -- v3\.5\.0 +- v3\.6\.0 - Release Summary - Minor Changes -- v3\.4\.0 +- v3\.5\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.3\.0 +- v3\.4\.0 - Release Summary - Minor Changes -- v3\.2\.0 + - Bugfixes +- v3\.3\.0 - Release Summary - Minor Changes -- v3\.1\.0 +- v3\.2\.0 - Release Summary - Minor Changes - - Bugfixes -- v3\.0\.0 +- v3\.1\.0 - Release Summary + - Minor Changes + - Bugfixes +- v3\.0\.0 + - Release Summary - Breaking Changes / Porting Guide - Removed Features \(previously deprecated\) - v2\.20\.0 - - Release Summary - - Minor Changes -- v2\.19\.0 - Release Summary - Minor Changes -- v2\.18\.0 +- v2\.19\.0 - Release Summary - Minor Changes - - Deprecated Features - - Bugfixes -- v2\.17\.0 +- v2\.18\.0 - Release Summary - Minor Changes -- v2\.16\.0 + - Deprecated Features + - Bugfixes +- v2\.17\.0 - Release Summary - Minor Changes -- v2\.15\.0 +- v2\.16\.0 - Release Summary - Minor Changes -- v2\.14\.0 +- v2\.15\.0 - Release Summary - Minor Changes -- v2\.13\.0 +- v2\.14\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.12\.0 +- v2\.13\.0 - Release Summary - Minor Changes -- v2\.11\.0 + - Bugfixes +- v2\.12\.0 - Release Summary - Minor Changes -- v2\.10\.0 +- v2\.11\.0 - Release Summary - Minor Changes - - Bugfixes -- v2\.9\.0 +- v2\.10\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.8\.3 +- v2\.9\.0 - Release Summary + - Minor Changes + - Bugfixes +- v2\.8\.3 + - Release Summary - Known Issues - v2\.8\.2 - - Release Summary - - Bugfixes -- v2\.8\.1 - Release Summary - Bugfixes -- v2\.8\.0 +- v2\.8\.1 - Release Summary - - Minor Changes - Bugfixes -- v2\.7\.0 +- v2\.8\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.6\.0 +- v2\.7\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.5\.0 +- v2\.6\.0 - Release Summary - Minor Changes - Bugfixes -- v2\.4\.0 +- v2\.5\.0 - Release Summary - Minor Changes - Bugfixes - - Known Issues -- v2\.3\.1 +- v2\.4\.0 - Release Summary - - Known Issues -- v2\.3\.0 - - Release Summary - Minor Changes - Bugfixes -- v2\.2\.1 + - Known Issues +- v2\.3\.1 + - Release Summary + - Known Issues +- v2\.3\.0 - Release Summary - - Bugfixes -- v2\.2\.0 - - Release Summary - Minor Changes + - Bugfixes +- v2\.2\.1 + - Release Summary - Bugfixes - - New Modules -- v2\.1\.0 +- v2\.2\.0 - Release Summary - Minor Changes - Bugfixes - - New Modules -- v2\.0\.0 + - New Modules +- v2\.1\.0 - Release Summary - Minor Changes - - Breaking Changes / Porting Guide - Bugfixes + - New Modules +- v2\.0\.0 + - Release Summary + - Minor Changes + - Breaking Changes / Porting Guide + - Bugfixes - New Plugins - Filter - v1\.2\.0 - - Release Summary - - Minor Changes - - Bugfixes -- v1\.1\.0 - Release Summary - Minor Changes -- v1\.0\.1 - - Release Summary - Bugfixes -- v1\.0\.0 +- v1\.1\.0 + - Release Summary + - Minor Changes +- v1\.0\.1 - Release Summary - Bugfixes -- v0\.1\.1 +- v1\.0\.0 - Release Summary - Bugfixes -- v0\.1\.0 +- v0\.1\.1 - Release Summary - - Minor Changes + - Bugfixes +- v0\.1\.0 + - Release Summary + - Minor Changes - -## v3\.8\.1 + +## v3\.9\.0 ### Release Summary -Bugfix release\. +Bugfix and feature release\. + + +### Minor Changes + +* api\_info\, api modify \- add remote\-log\-format\, remote\-protocol\, and event\-delimiter to system logging action \([https\://github\.com/ansible\-collections/community\.routeros/pull/381](https\://github\.com/ansible\-collections/community\.routeros/pull/381)\)\. +* api\_info\, api\_modify \- add disable\-link\-local\-address and stale\-neighbor\-timeout fields to ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/380](https\://github\.com/ansible\-collections/community\.routeros/pull/380)\)\. +* api\_info\, api\_modify \- adjust neighbor limit fields in ipv6 settings to match RouterOS 7\.18 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/380](https\://github\.com/ansible\-collections/community\.routeros/pull/380)\)\. +* api\_info\, api\_modify \- set passthrough default in ip firewall mangle to true for RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/382](https\://github\.com/ansible\-collections/community\.routeros/pull/382)\)\. +* api\_info\, api\_modify \- since RouterOS 7\.17 VRF is supported for OVPN server\. It now supports multiple entries\, while api\_modify so far only accepted a single entry\. The interface ovpn\-server server path now allows multiple entries on RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/383](https\://github\.com/ansible\-collections/community\.routeros/pull/383)\)\. ### Bugfixes +* routeros terminal plugin \- fix terminal\_stdout\_re pattern to handle long system identities when connecting to RouterOS through SSH \([https\://github\.com/ansible\-collections/community\.routeros/pull/386](https\://github\.com/ansible\-collections/community\.routeros/pull/386)\)\. + + +## v3\.8\.1 + + +### Release Summary + +Bugfix release\. + + +### Bugfixes + * facts and api\_facts modules \- prevent deprecation warnings when used with ansible\-core 2\.19 \([https\://github\.com/ansible\-collections/community\.routeros/pull/384](https\://github\.com/ansible\-collections/community\.routeros/pull/384)\)\. ## v3\.8\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ethernet switch port\-isolation which is supported since RouterOS 6\.43 \([https\://github\.com/ansible\-collections/community\.routeros/pull/375](https\://github\.com/ansible\-collections/community\.routeros/pull/375)\)\. @@ -185,20 +211,6 @@ Feature release\. ## v3\.7\.0 - -### Release Summary - -Feature release\. - - -### Minor Changes - -* api\_find\_and\_modify \- allow to control whether dynamic and/or builtin entries are ignored with the new ignore\_dynamic and ignore\_builtin options \([https\://github\.com/ansible\-collections/community\.routeros/issues/372](https\://github\.com/ansible\-collections/community\.routeros/issues/372)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/373](https\://github\.com/ansible\-collections/community\.routeros/pull/373)\)\. -* api\_info\, api\_modify \- add port\-cost\-mode to interface bridge which is supported since RouterOS 7\.13 \([https\://github\.com/ansible\-collections/community\.routeros/pull/371](https\://github\.com/ansible\-collections/community\.routeros/pull/371)\)\. - - -## v3\.6\.0 - ### Release Summary @@ -207,12 +219,11 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. -* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. -* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. +* api\_find\_and\_modify \- allow to control whether dynamic and/or builtin entries are ignored with the new ignore\_dynamic and ignore\_builtin options \([https\://github\.com/ansible\-collections/community\.routeros/issues/372](https\://github\.com/ansible\-collections/community\.routeros/issues/372)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/373](https\://github\.com/ansible\-collections/community\.routeros/pull/373)\)\. +* api\_info\, api\_modify \- add port\-cost\-mode to interface bridge which is supported since RouterOS 7\.13 \([https\://github\.com/ansible\-collections/community\.routeros/pull/371](https\://github\.com/ansible\-collections/community\.routeros/pull/371)\)\. - -## v3\.5\.0 + +## v3\.6\.0 ### Release Summary @@ -222,22 +233,37 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add mdns\-repeat\-ifaces to ip dns for RouterOS 7\.16 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/358](https\://github\.com/ansible\-collections/community\.routeros/pull/358)\)\. +* api\_info\, api\_modify \- field name change in routing bgp connection path implemented by RouterOS 7\.19 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/360](https\://github\.com/ansible\-collections/community\.routeros/pull/360)\)\. +* api\_info\, api\_modify \- rename is\-responder property in interface wireguard peers to responder for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\. + + +## v3\.5\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- change default for /ip/cloud/ddns\-enabled for RouterOS 7\.17 and newer from yes to auto \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\. ## v3\.4\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns forwarders path implemented by RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/343](https\://github\.com/ansible\-collections/community\.routeros/pull/343)\)\. - + ### Bugfixes * api\_info\, api\_modify \- remove the primary key action from the interface wifi provisioning path\, since RouterOS also allows to create completely duplicate entries \([https\://github\.com/ansible\-collections/community\.routeros/issues/344](https\://github\.com/ansible\-collections/community\.routeros/issues/344)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/345](https\://github\.com/ansible\-collections/community\.routeros/pull/345)\)\. @@ -245,12 +271,12 @@ Feature and bugfix release\. ## v3\.3\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing attribute require\-message\-auth for the radius path which exists since RouterOS version 7\.15 \([https\://github\.com/ansible\-collections/community\.routeros/issues/338](https\://github\.com/ansible\-collections/community\.routeros/issues/338)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/339](https\://github\.com/ansible\-collections/community\.routeros/pull/339)\)\. @@ -261,12 +287,12 @@ Feature release\. ## v3\.2\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the routing filter community\-list path implemented by RouterOS 7 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/331](https\://github\.com/ansible\-collections/community\.routeros/pull/331)\)\. @@ -274,17 +300,17 @@ Feature release\. ## v3\.1\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing fields comment\, next\-pool to ip pool path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\. - + ### Bugfixes * api\_info\, api\_modify \- fields log and log\-prefix in paths ip firewall filter\, ip firewall mangle\, ip firewall nat\, ip firewall raw now have the correct default values \([https\://github\.com/ansible\-collections/community\.routeros/pull/324](https\://github\.com/ansible\-collections/community\.routeros/pull/324)\)\. @@ -292,7 +318,7 @@ Bugfix and feature release\. ## v3\.0\.0 - + ### Release Summary Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\. @@ -310,12 +336,12 @@ Major release that drops support for End of Life Python versions and fixes check ## v2\.20\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add new parameters from the RouterOS 7\.16 release \([https\://github\.com/ansible\-collections/community\.routeros/pull/323](https\://github\.com/ansible\-collections/community\.routeros/pull/323)\)\. @@ -326,12 +352,12 @@ Feature release\. ## v2\.19\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add support for the ip dns adlist path implemented by RouterOS 7\.15 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/310](https\://github\.com/ansible\-collections/community\.routeros/pull/310)\)\. @@ -343,12 +369,12 @@ Feature release\. ## v2\.18\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info \- allow to restrict the output by limiting fields to specific values with the new restrict option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -364,7 +390,7 @@ Feature release\. * The collection deprecates support for all Ansible/ansible\-base/ansible\-core versions that are currently End of Life\, [according to the ansible\-core support matrix](https\://docs\.ansible\.com/ansible\-core/devel/reference\_appendices/release\_and\_maintenance\.html\#ansible\-core\-support\-matrix)\. This means that the next major release of the collection will no longer support Ansible 2\.9\, ansible\-base 2\.10\, ansible\-core 2\.11\, ansible\-core 2\.12\, ansible\-core 2\.13\, and ansible\-core 2\.14\. - + ### Bugfixes * api\_modify\, api\_info \- change the default of ingress\-filtering in paths interface bridge and interface bridge port back to false for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\. @@ -372,21 +398,6 @@ Feature release\. ## v2\.17\.0 - -### Release Summary - -Feature release\. - - -### Minor Changes - -* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. -* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. -* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - - -## v2\.16\.0 - ### Release Summary @@ -395,11 +406,12 @@ Feature release\. ### Minor Changes -* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. -* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. +* api\_info\, api\_modify \- add system health settings path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\. +* api\_info\, api\_modify \- add missing path /system resource irq rps \([https\://github\.com/ansible\-collections/community\.routeros/pull/295](https\://github\.com/ansible\-collections/community\.routeros/pull/295)\)\. +* api\_info\, api\_modify \- add parameter host\-key\-type for ip ssh path \([https\://github\.com/ansible\-collections/community\.routeros/issues/280](https\://github\.com/ansible\-collections/community\.routeros/issues/280)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/297](https\://github\.com/ansible\-collections/community\.routeros/pull/297)\)\. - -## v2\.15\.0 + +## v2\.16\.0 ### Release Summary @@ -409,6 +421,20 @@ Feature release\. ### Minor Changes +* api\_info\, api\_modify \- add missing path /ppp secret \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\. +* api\_info\, api\_modify \- minor changes /interface ethernet path fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/288](https\://github\.com/ansible\-collections/community\.routeros/pull/288)\)\. + + +## v2\.15\.0 + + +### Release Summary + +Feature release\. + + +### Minor Changes + * api\_info\, api\_modify \- Add RouterOS 7\.x support to /mpls ldp path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\. * api\_info\, api\_modify \- add /ip route rule path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/278](https\://github\.com/ansible\-collections/community\.routeros/pull/278)\)\. * api\_info\, api\_modify \- add /routing filter path for RouterOS 6\.x \([https\://github\.com/ansible\-collections/community\.routeros/pull/279](https\://github\.com/ansible\-collections/community\.routeros/pull/279)\)\. @@ -423,12 +449,12 @@ Feature release\. ## v2\.14\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add read\-only fields installed\-version\, latest\-version and status in system package update \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\. @@ -438,18 +464,18 @@ Feature release\. ## v2\.13\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- make path user group modifiable and add comment attribute \([https\://github\.com/ansible\-collections/community\.routeros/issues/256](https\://github\.com/ansible\-collections/community\.routeros/issues/256)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/257](https\://github\.com/ansible\-collections/community\.routeros/pull/257)\)\. * api\_modify\, api\_info \- add support for the ip vrf path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\) - + ### Bugfixes * facts \- fix date not getting removed for idempotent config export \([https\://github\.com/ansible\-collections/community\.routeros/pull/262](https\://github\.com/ansible\-collections/community\.routeros/pull/262)\)\. @@ -457,12 +483,12 @@ Bugfix and feature release\. ## v2\.12\.0 - + ### Release Summary Feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add interface ovpn\-client path \([https\://github\.com/ansible\-collections/community\.routeros/issues/242](https\://github\.com/ansible\-collections/community\.routeros/issues/242)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/244](https\://github\.com/ansible\-collections/community\.routeros/pull/244)\)\. @@ -476,12 +502,12 @@ Feature release\. ## v2\.11\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- add missing DoH parameters doh\-max\-concurrent\-queries\, doh\-max\-server\-connections\, and doh\-timeout to the ip dns path \([https\://github\.com/ansible\-collections/community\.routeros/issues/230](https\://github\.com/ansible\-collections/community\.routeros/issues/230)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/235](https\://github\.com/ansible\-collections/community\.routeros/pull/235)\) @@ -496,12 +522,12 @@ Feature and bugfix release\. ## v2\.10\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info \- add new include\_read\_only option to select behavior for read\-only values\. By default these are not returned \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. @@ -525,7 +551,7 @@ Bugfix and feature release\. * api\_modify \- add new handle\_read\_only and handle\_write\_only options to handle the module\'s behavior for read\-only and write\-only fields \([https\://github\.com/ansible\-collections/community\.routeros/pull/213](https\://github\.com/ansible\-collections/community\.routeros/pull/213)\)\. * api\_modify\, api\_info \- support API paths routing id\, routing bgp connection \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\. - + ### Bugfixes * api\_info\, api\_modify \- in the snmp path\, ensure that engine\-id\-suffix is only available on RouterOS 7\.10\+\, and that engine\-id is read\-only on RouterOS 7\.10\+ \([https\://github\.com/ansible\-collections/community\.routeros/issues/208](https\://github\.com/ansible\-collections/community\.routeros/issues/208)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/218](https\://github\.com/ansible\-collections/community\.routeros/pull/218)\)\. @@ -533,18 +559,18 @@ Bugfix and feature release\. ## v2\.9\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * api\_info\, api\_modify \- add path caps\-man channel and enable path caps\-man manager interface \([https\://github\.com/ansible\-collections/community\.routeros/issues/193](https\://github\.com/ansible\-collections/community\.routeros/issues/193)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/194](https\://github\.com/ansible\-collections/community\.routeros/pull/194)\)\. * api\_info\, api\_modify \- add path ip traffic\-flow target \([https\://github\.com/ansible\-collections/community\.routeros/issues/191](https\://github\.com/ansible\-collections/community\.routeros/issues/191)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/192](https\://github\.com/ansible\-collections/community\.routeros/pull/192)\)\. - + ### Bugfixes * api\_modify\, api\_info \- add missing parameter engine\-id\-suffix for the snmp path \([https\://github\.com/ansible\-collections/community\.routeros/issues/189](https\://github\.com/ansible\-collections/community\.routeros/issues/189)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/190](https\://github\.com/ansible\-collections/community\.routeros/pull/190)\)\. @@ -552,7 +578,7 @@ Bugfix and feature release\. ## v2\.8\.3 - + ### Release Summary Maintenance release with updated documentation\. @@ -573,19 +599,6 @@ for the rendered HTML version of the documentation of the latest release\. ## v2\.8\.2 - -### Release Summary - -Bugfix release\. - - -### Bugfixes - -* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - - -## v2\.8\.1 - ### Release Summary @@ -594,35 +607,23 @@ Bugfix release\. ### Bugfixes -* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. +* api\_modify\, api\_info \- add missing parameter tls for the tool e\-mail path \([https\://github\.com/ansible\-collections/community\.routeros/issues/179](https\://github\.com/ansible\-collections/community\.routeros/issues/179)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/180](https\://github\.com/ansible\-collections/community\.routeros/pull/180)\)\. - -## v2\.8\.0 + +## v2\.8\.1 ### Release Summary -Bugfix and feature release\. - - -### Minor Changes - -* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. -* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. -* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. -* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. -* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. +Bugfix release\. ### Bugfixes -* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. -* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. +* facts \- do not crash in CLI output preprocessing in unexpected situations during line unwrapping \([https\://github\.com/ansible\-collections/community\.routeros/issues/170](https\://github\.com/ansible\-collections/community\.routeros/issues/170)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/177](https\://github\.com/ansible\-collections/community\.routeros/pull/177)\)\. - -## v2\.7\.0 + +## v2\.8\.0 ### Release Summary @@ -632,28 +633,53 @@ Bugfix and feature release\. ### Minor Changes -* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. +* api\_modify \- adapt data for API paths ip dhcp\-server network \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\. +* api\_modify \- add support for API path snmp community \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support for trap\-interfaces in API path snmp \([https\://github\.com/ansible\-collections/community\.routeros/pull/159](https\://github\.com/ansible\-collections/community\.routeros/pull/159)\)\. +* api\_modify \- add support to disable IPv6 in API paths ipv6 settings \([https\://github\.com/ansible\-collections/community\.routeros/pull/158](https\://github\.com/ansible\-collections/community\.routeros/pull/158)\)\. +* api\_modify \- support API paths ip firewall layer7\-protocol \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\. +* command \- workaround for extra characters in stdout in RouterOS versions between 6\.49 and 7\.1\.5 \([https\://github\.com/ansible\-collections/community\.routeros/issues/62](https\://github\.com/ansible\-collections/community\.routeros/issues/62)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/161](https\://github\.com/ansible\-collections/community\.routeros/pull/161)\)\. ### Bugfixes +* api\_info\, api\_modify \- fix default and remove behavior for dhcp\-options in path ip dhcp\-client \([https\://github\.com/ansible\-collections/community\.routeros/issues/148](https\://github\.com/ansible\-collections/community\.routeros/issues/148)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* api\_modify \- fix handling of disabled keys on creation \([https\://github\.com/ansible\-collections/community\.routeros/pull/154](https\://github\.com/ansible\-collections/community\.routeros/pull/154)\)\. +* various plugins and modules \- remove unnecessary imports \([https\://github\.com/ansible\-collections/community\.routeros/pull/149](https\://github\.com/ansible\-collections/community\.routeros/pull/149)\)\. + + +## v2\.7\.0 + + +### Release Summary + +Bugfix and feature release\. + + +### Minor Changes + +* api\_modify\, api\_info \- support API paths ip arp\, ip firewall raw\, ipv6 firewall raw \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. + + +### Bugfixes + * api\_modify\, api\_info \- defaults corrected for fields in interface wireguard peers API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\. ## v2\.6\.0 - + ### Release Summary Regular bugfix and feature release\. - + ### Minor Changes * api\_modify\, api\_info \- add field regexp to ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. * api\_modify\, api\_info \- support API paths interface wireguard\, interface wireguard peers \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\. - + ### Bugfixes * api\_modify \- do not use name as a unique key in ip dns static \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\. @@ -662,17 +688,17 @@ Regular bugfix and feature release\. ## v2\.5\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * api\_info\, api\_modify \- support API paths interface ethernet poe\, interface gre6\, interface vrrp and also support all previously missing fields of entries in ip dhcp\-server \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. - + ### Bugfixes * api\_modify \- address\-pool field of entries in API path ip dhcp\-server is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\. @@ -680,12 +706,12 @@ Feature and bugfix release\. ## v2\.4\.0 - + ### Release Summary Feature release improving the api\* modules\. - + ### Minor Changes * api\* modules \- Add new option force\_no\_cert to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\. @@ -706,7 +732,7 @@ Feature release improving the api\* modules\. * api\_modify\, api\_info \- support for fields blackhole\, pref\-src\, routing\-table\, suppress\-hw\-offload\, type\, vrf\-interface in ip route path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. * api\_modify\, api\_info \- support paths system ntp client servers and system ntp server available in ROS7\, as well as new fields servers\, mode\, and vrf for system ntp client \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\. - + ### Bugfixes * api\_modify \- ip route entry can be defined without the need of gateway field\, which is correct for unreachable/blackhole type of routes \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\. @@ -724,7 +750,7 @@ Feature release improving the api\* modules\. ## v2\.3\.1 - + ### Release Summary Maintenance release with improved documentation\. @@ -737,19 +763,19 @@ Maintenance release with improved documentation\. ## v2\.3\.0 - + ### Release Summary Feature and bugfix release\. - + ### Minor Changes * The collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.routeros/pull/108](https\://github\.com/ansible\-collections/community\.routeros/pull/108)\)\. * api\* modules \- added timeout parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\. * api\_modify\, api\_info \- support API path ip firewall mangle \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server support script\, and ip firewall nat support in\-interface and in\-interface\-list \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\. @@ -757,12 +783,12 @@ Feature and bugfix release\. ## v2\.2\.1 - + ### Release Summary Bugfix release\. - + ### Bugfixes * api\_modify\, api\_info \- make API path ip dhcp\-server lease support server\=all \([https\://github\.com/ansible\-collections/community\.routeros/issues/104](https\://github\.com/ansible\-collections/community\.routeros/issues/104)\, [https\://github\.com/ansible\-collections/community\.routeros/pull/107](https\://github\.com/ansible\-collections/community\.routeros/pull/107)\)\. @@ -771,17 +797,17 @@ Bugfix release\. ## v2\.2\.0 - + ### Release Summary New feature release\. - + ### Minor Changes * All software licenses are now in the LICENSES/ directory of the collection root\. Moreover\, SPDX\-License\-Identifier\: is used to declare the applicable license for every file that is not automatically generated \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. - + ### Bugfixes * Include LICENSES/BSD\-2\-Clause\.txt file for the routeros module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\. @@ -795,12 +821,12 @@ New feature release\. ## v2\.1\.0 - + ### Release Summary Feature and bugfix release with new modules\. - + ### Minor Changes * Added a community\.routeros\.api module defaults group\. Use with group/community\.routeros\.api to provide options for all API\-based modules \([https\://github\.com/ansible\-collections/community\.routeros/pull/89](https\://github\.com/ansible\-collections/community\.routeros/pull/89)\)\. @@ -809,7 +835,7 @@ Feature and bugfix release with new modules\. * api \- update query to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\. * api\* modules \- allow to set an encoding other than the default ASCII for communicating with the API \([https\://github\.com/ansible\-collections/community\.routeros/pull/95](https\://github\.com/ansible\-collections/community\.routeros/pull/95)\)\. - + ### Bugfixes * query \- fix query function check for \.id vs\. id arguments to not conflict with routeros arguments like identity \([https\://github\.com/ansible\-collections/community\.routeros/pull/68](https\://github\.com/ansible\-collections/community\.routeros/pull/68)\, [https\://github\.com/ansible\-collections/community\.routeros/issues/67](https\://github\.com/ansible\-collections/community\.routeros/issues/67)\)\. @@ -824,12 +850,12 @@ Feature and bugfix release with new modules\. ## v2\.0\.0 - + ### Release Summary A new major release with breaking changes in the behavior of community\.routeros\.api and community\.routeros\.command\. - + ### Minor Changes * api \- make validation of WHERE for query more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\. @@ -843,7 +869,7 @@ A new major release with breaking changes in the behavior of community\.ro * api \- splitting commands no longer uses a naive split by whitespace\, but a more RouterOS CLI compatible splitting algorithm \([https\://github\.com/ansible\-collections/community\.routeros/pull/45](https\://github\.com/ansible\-collections/community\.routeros/pull/45)\)\. * command \- the module now always indicates that a change happens\. If this is not correct\, please use changed\_when to determine the correct changed status for a task \([https\://github\.com/ansible\-collections/community\.routeros/pull/50](https\://github\.com/ansible\-collections/community\.routeros/pull/50)\)\. - + ### Bugfixes * api \- improve splitting of WHERE queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\. @@ -865,12 +891,12 @@ A new major release with breaking changes in the behavior of community\.ro ## v1\.2\.0 - + ### Release Summary Bugfix and feature release\. - + ### Minor Changes * Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.routeros/pull/38](https\://github\.com/ansible\-collections/community\.routeros/pull/38)\)\. @@ -878,7 +904,7 @@ Bugfix and feature release\. * api \- rename option ssl to tls\, and keep the old name as an alias \([https\://github\.com/ansible\-collections/community\.routeros/pull/37](https\://github\.com/ansible\-collections/community\.routeros/pull/37)\)\. * fact \- add fact ansible\_net\_config\_nonverbose to get idempotent config \(no date\, no verbose\) \([https\://github\.com/ansible\-collections/community\.routeros/pull/23](https\://github\.com/ansible\-collections/community\.routeros/pull/23)\)\. - + ### Bugfixes * api \- when using TLS/SSL\, remove explicit cipher configuration to insecure values\, which also makes it impossible to connect to newer RouterOS versions \([https\://github\.com/ansible\-collections/community\.routeros/pull/34](https\://github\.com/ansible\-collections/community\.routeros/pull/34)\)\. @@ -886,12 +912,12 @@ Bugfix and feature release\. ## v1\.1\.0 - + ### Release Summary This release allow dashes in usernames for SSH\-based modules\. - + ### Minor Changes * command \- added support for a dash \(\-\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\. @@ -900,12 +926,12 @@ This release allow dashes in usernames for SSH\-based modules\. ## v1\.0\.1 - + ### Release Summary Maintenance release with a bugfix for api\. - + ### Bugfixes * api \- remove id to \.id as default requirement which conflicts with RouterOS id configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\. @@ -913,12 +939,12 @@ Maintenance release with a bugfix for api\. ## v1\.0\.0 - + ### Release Summary This is the first production \(non\-prerelease\) release of community\.routeros\. - + ### Bugfixes * routeros terminal plugin \- allow slashes in hostnames for terminal detection\. Without this\, slashes in hostnames will result in connection timeouts \([https\://github\.com/ansible\-collections/community\.network/pull/138](https\://github\.com/ansible\-collections/community\.network/pull/138)\)\. @@ -926,12 +952,12 @@ This is the first production \(non\-prerelease\) release of community\.rou ## v0\.1\.1 - + ### Release Summary Small improvements and bugfixes over the initial release\. - + ### Bugfixes * api \- fix crash when the ssl parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\. @@ -939,12 +965,12 @@ Small improvements and bugfixes over the initial release\. ## v0\.1\.0 - + ### Release Summary The community\.routeros continues the work on the Ansible RouterOS modules from their state in community\.network 1\.2\.0\. The changes listed here are thus relative to the modules community\.network\.routeros\_\*\. - + ### Minor Changes * facts \- now also collecting data about BGP and OSPF \([https\://github\.com/ansible\-collections/community\.network/pull/101](https\://github\.com/ansible\-collections/community\.network/pull/101)\)\. diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2e73ef4..3fc3b05 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,28 @@ Community RouterOS Release Notes .. contents:: Topics +v3.9.0 +====== + +Release Summary +--------------- + +Bugfix and feature release. + +Minor Changes +------------- + +- api_info, api modify - add ``remote-log-format``, ``remote-protocol``, and ``event-delimiter`` to ``system logging action`` (https://github.com/ansible-collections/community.routeros/pull/381). +- api_info, api_modify - add ``disable-link-local-address`` and ``stale-neighbor-timeout`` fields to ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/380). +- api_info, api_modify - adjust neighbor limit fields in ``ipv6 settings`` to match RouterOS 7.18 and newer (https://github.com/ansible-collections/community.routeros/pull/380). +- api_info, api_modify - set ``passthrough`` default in ``ip firewall mangle`` to ``true`` for RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/382). +- api_info, api_modify - since RouterOS 7.17 VRF is supported for OVPN server. It now supports multiple entries, while ``api_modify`` so far only accepted a single entry. The ``interface ovpn-server server`` path now allows multiple entries on RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/383). + +Bugfixes +-------- + +- routeros terminal plugin - fix ``terminal_stdout_re`` pattern to handle long system identities when connecting to RouterOS through SSH (https://github.com/ansible-collections/community.routeros/pull/386). + v3.8.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index df9d0e0..1ba1857 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -944,3 +944,30 @@ releases: - 3.8.1.yml - 384-warnings.yml release_date: '2025-07-26' + 3.9.0: + changes: + bugfixes: + - routeros terminal plugin - fix ``terminal_stdout_re`` pattern to handle + long system identities when connecting to RouterOS through SSH (https://github.com/ansible-collections/community.routeros/pull/386). + minor_changes: + - api_info, api modify - add ``remote-log-format``, ``remote-protocol``, and + ``event-delimiter`` to ``system logging action`` (https://github.com/ansible-collections/community.routeros/pull/381). + - api_info, api_modify - add ``disable-link-local-address`` and ``stale-neighbor-timeout`` + fields to ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/380). + - api_info, api_modify - adjust neighbor limit fields in ``ipv6 settings`` + to match RouterOS 7.18 and newer (https://github.com/ansible-collections/community.routeros/pull/380). + - api_info, api_modify - set ``passthrough`` default in ``ip firewall mangle`` + to ``true`` for RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/382). + - api_info, api_modify - since RouterOS 7.17 VRF is supported for OVPN server. + It now supports multiple entries, while ``api_modify`` so far only accepted + a single entry. The ``interface ovpn-server server`` path now allows multiple + entries on RouterOS 7.17 and newer (https://github.com/ansible-collections/community.routeros/pull/383). + release_summary: Bugfix and feature release. + fragments: + - 3.9.0.yml + - 380-ipv6-settings.yml + - 381-logging-cef.yml + - 382-mangle-passthrough.yml + - 385-vrf-support-for-ovpn-server.yml + - 386-fix-pattern-to-handle-long-identity.yml + release_date: '2025-08-10' diff --git a/changelogs/fragments/3.9.0.yml b/changelogs/fragments/3.9.0.yml deleted file mode 100644 index 56de6d9..0000000 --- a/changelogs/fragments/3.9.0.yml +++ /dev/null @@ -1 +0,0 @@ -release_summary: Bugfix and feature release. diff --git a/changelogs/fragments/380-ipv6-settings.yml b/changelogs/fragments/380-ipv6-settings.yml deleted file mode 100644 index a8c6e9b..0000000 --- a/changelogs/fragments/380-ipv6-settings.yml +++ /dev/null @@ -1,3 +0,0 @@ -minor_changes: - - api_info, api_modify - add ``disable-link-local-address`` and ``stale-neighbor-timeout`` fields to ``ipv6 settings`` (https://github.com/ansible-collections/community.routeros/pull/380). - - api_info, api_modify - adjust neighbor limit fields in ``ipv6 settings`` to match RouterOS 7.18 and newer (https://github.com/ansible-collections/community.routeros/pull/380). diff --git a/changelogs/fragments/381-logging-cef.yml b/changelogs/fragments/381-logging-cef.yml deleted file mode 100644 index 849f82a..0000000 --- a/changelogs/fragments/381-logging-cef.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api modify - add ``remote-log-format``, ``remote-protocol``, and ``event-delimiter`` to ``system logging action`` (https://github.com/ansible-collections/community.routeros/pull/381). diff --git a/changelogs/fragments/382-mangle-passthrough.yml b/changelogs/fragments/382-mangle-passthrough.yml deleted file mode 100644 index 2123dfa..0000000 --- a/changelogs/fragments/382-mangle-passthrough.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - api_info, api_modify - set ``passthrough`` default in ``ip firewall mangle`` to ``true`` for RouterOS 7.19 and newer (https://github.com/ansible-collections/community.routeros/pull/382). diff --git a/changelogs/fragments/385-vrf-support-for-ovpn-server.yml b/changelogs/fragments/385-vrf-support-for-ovpn-server.yml deleted file mode 100644 index 4790a9d..0000000 --- a/changelogs/fragments/385-vrf-support-for-ovpn-server.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -minor_changes: - - api_info, api_modify - since RouterOS 7.17 VRF is supported for OVPN server. - It now supports multiple entries, while ``api_modify`` so far only accepted a single entry. - The ``interface ovpn-server server`` path now allows multiple entries - on RouterOS 7.17 and newer - (https://github.com/ansible-collections/community.routeros/pull/383). diff --git a/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml b/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml deleted file mode 100644 index b9a749f..0000000 --- a/changelogs/fragments/386-fix-pattern-to-handle-long-identity.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: - - routeros terminal plugin - fix ``terminal_stdout_re`` pattern to handle long system identities when connecting to RouterOS through SSH (https://github.com/ansible-collections/community.routeros/pull/386). From 3b05f8a4cd559543e3e58222af083a1125916107 Mon Sep 17 00:00:00 2001 From: hansmi Date: Mon, 11 Aug 2025 19:59:46 +0200 Subject: [PATCH 362/365] Add show-at-cli-login property for system note (#392) RouterOS 7.14 (March 2024) added `show-at-cli-login` in `system note`. --- changelogs/fragments/392-sys-note-cli-login.yml | 2 ++ plugins/module_utils/_api_data.py | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/fragments/392-sys-note-cli-login.yml diff --git a/changelogs/fragments/392-sys-note-cli-login.yml b/changelogs/fragments/392-sys-note-cli-login.yml new file mode 100644 index 0000000..618db86 --- /dev/null +++ b/changelogs/fragments/392-sys-note-cli-login.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - add ``show-at-cli-login`` property in ``system note`` (https://github.com/ansible-collections/community.routeros/pull/392). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index 2b44b8b..fb4f919 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -4421,6 +4421,9 @@ PATHS = { unversioned=VersionedAPIData( single_value=True, fully_understood=True, + versioned_fields=[ + ([('7.14', '>=')], 'show-at-cli-login', KeyInfo(default=False)), + ], fields={ 'note': KeyInfo(default=''), 'show-at-login': KeyInfo(default=True), From db716c13687a7c09de769076e111ff95a68f54a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:12:53 +0200 Subject: [PATCH 363/365] Bump actions/checkout from 4 to 5 in the ci group (#393) Bumps the ci group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4 to 5 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major dependency-group: ci ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nox.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nox.yml b/.github/workflows/nox.yml index 43cce99..a539157 100644 --- a/.github/workflows/nox.yml +++ b/.github/workflows/nox.yml @@ -21,7 +21,7 @@ jobs: name: "Run extra sanity tests" steps: - name: Check out collection - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false - name: Run nox From fb070e4ac65e851bd3bb7d5afdb594c9d2ab07fe Mon Sep 17 00:00:00 2001 From: hansmi Date: Sun, 17 Aug 2025 12:55:56 +0200 Subject: [PATCH 364/365] Set default value for interface list include/exclude (#394) Without a default value a pre-existing value isn't removed unless the caller specifies the property. --- changelogs/fragments/394-iface-list-defaults.yml | 2 ++ plugins/module_utils/_api_data.py | 4 ++-- tests/unit/plugins/modules/test_api_info.py | 8 -------- 3 files changed, 4 insertions(+), 10 deletions(-) create mode 100644 changelogs/fragments/394-iface-list-defaults.yml diff --git a/changelogs/fragments/394-iface-list-defaults.yml b/changelogs/fragments/394-iface-list-defaults.yml new file mode 100644 index 0000000..7e517a6 --- /dev/null +++ b/changelogs/fragments/394-iface-list-defaults.yml @@ -0,0 +1,2 @@ +minor_changes: + - api_info, api_modify - set default value for ``include`` and ``exclude`` properties in ``system note`` to an empty string (https://github.com/ansible-collections/community.routeros/pull/394). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index fb4f919..f1d131d 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -441,8 +441,8 @@ PATHS = { fully_understood=True, fields={ 'comment': KeyInfo(can_disable=True, remove_value=''), - 'exclude': KeyInfo(), - 'include': KeyInfo(), + 'exclude': KeyInfo(default=''), + 'include': KeyInfo(default=''), 'name': KeyInfo(), }, ), diff --git a/tests/unit/plugins/modules/test_api_info.py b/tests/unit/plugins/modules/test_api_info.py index 967a854..0fac95a 100644 --- a/tests/unit/plugins/modules/test_api_info.py +++ b/tests/unit/plugins/modules/test_api_info.py @@ -470,8 +470,6 @@ class TestRouterosApiInfoModule(ModuleTestCase): { '.id': '*2000010', 'name': 'WAN', - 'include': '', - 'exclude': '', 'comment': 'defconf', }, ]) @@ -523,24 +521,18 @@ class TestRouterosApiInfoModule(ModuleTestCase): { '.id': '*2000000', 'name': 'all', - 'include': '', - 'exclude': '', 'builtin': True, 'comment': 'contains all interfaces', }, { '.id': '*2000001', 'name': 'none', - 'include': '', - 'exclude': '', 'builtin': True, 'comment': 'contains no interfaces', }, { '.id': '*2000010', 'name': 'WAN', - 'include': '', - 'exclude': '', 'builtin': False, 'comment': 'defconf', }, From f6aeae1abd5cd774be13c4f596e915e135d9024d Mon Sep 17 00:00:00 2001 From: Claudio Luck <870386+cluck@users.noreply.github.com> Date: Tue, 19 Aug 2025 22:46:38 +0200 Subject: [PATCH 365/365] Handle IP addresses configured on disappeared interfaces (#391) * Handle IP addresses configured on disappeared interfaces * Handle IP addresses configured on disappeared interfaces Always set type property, add changelog fragment * Handle IP addresses configured on disappeared interfaces (wording) Co-authored-by: Felix Fontein --------- Co-authored-by: Claudio Luck Co-authored-by: Felix Fontein --- .../fragments/391-report-unknown-interfaces.yml | 12 ++++++++++++ plugins/modules/api_facts.py | 8 +++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/391-report-unknown-interfaces.yml diff --git a/changelogs/fragments/391-report-unknown-interfaces.yml b/changelogs/fragments/391-report-unknown-interfaces.yml new file mode 100644 index 0000000..bcef417 --- /dev/null +++ b/changelogs/fragments/391-report-unknown-interfaces.yml @@ -0,0 +1,12 @@ +--- +bugfixes: + - | + api_facts - also report interfaces that are inferred only by reference by IP addresses. + RouterOS's APIs have IPv4 and IPv6 addresses point at interfaces by their name, which can + change over time and in-between API calls, such that interfaces may have been enumerated + under another name, or not at all (for example when removed). Such interfaces are now reported + under their new or temporary name and with a synthetic ``type`` property set to differentiate + the more likely and positively confirmed removal case (with ``type: "ansible:unknown"``) from + the unlikely and probably transient naming mismatch (with ``type: "ansible:mismatch"``). + Previously, the api_facts module would have crashed with a ``KeyError`` exception + (https://github.com/ansible-collections/community.routeros/pull/391). diff --git a/plugins/modules/api_facts.py b/plugins/modules/api_facts.py index 09c0fbb..d0f6b00 100644 --- a/plugins/modules/api_facts.py +++ b/plugins/modules/api_facts.py @@ -317,8 +317,10 @@ class Interfaces(FactsBase): def populate_addresses(self, data, family): for value in data: key = value['interface'] - if family not in self.facts['interfaces'][key]: - self.facts['interfaces'][key][family] = [] + iface = self.facts['interfaces'].setdefault(key, ( + {"type": "ansible:unknown"} if key.startswith('*') else + {"type": "ansible:mismatch"})) + iface_addrs = iface.setdefault(family, []) addr, subnet = value['address'].split('/') subnet = subnet.strip() # Try to convert subnet to an integer @@ -328,7 +330,7 @@ class Interfaces(FactsBase): pass ip = dict(address=addr.strip(), subnet=subnet) self.add_ip_address(addr.strip(), family) - self.facts['interfaces'][key][family].append(ip) + iface_addrs.append(ip) def add_ip_address(self, address, family): if family == 'ipv4':