mirror of
https://github.com/ansible-collections/community.routeros.git
synced 2025-08-03 09:44:49 +02:00
Compare commits
79 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7395011b0c | ||
|
8edc8018a7 | ||
|
e78df4a4cf | ||
|
c9d15bc43a | ||
|
008b5f893a | ||
|
b70b4a72b3 | ||
|
1f38be9e56 | ||
|
e988b18acf | ||
|
6e9d2e1379 | ||
|
1c182725ce | ||
|
9099fcd698 | ||
|
852e21a2f2 | ||
|
bb7eadbc9f | ||
|
d9be02bdb8 | ||
|
3475751b30 | ||
|
6008397375 | ||
|
b751d79a98 | ||
|
aa83116c78 | ||
|
4571d777de | ||
|
c7b2275f2c | ||
|
49e4b83594 | ||
|
88806047e3 | ||
|
221a697af9 | ||
|
ab1026504c | ||
|
bfd6b0bb13 | ||
|
f5b952751e | ||
|
5b81c157fe | ||
|
08152376de | ||
|
3af45c33f1 | ||
|
e52978b6d2 | ||
|
d1db4bec92 | ||
|
180e87fd5d | ||
|
81237dbde4 | ||
|
770e4d2c8d | ||
|
4b9925ac23 | ||
|
e286d768c0 | ||
|
9dba8082f9 | ||
|
3a34752296 | ||
|
a920caa16a | ||
|
9d382a1b10 | ||
|
2b1be7f011 | ||
|
8736996317 | ||
|
30a79061f3 | ||
|
ab446b4449 | ||
|
be9a7ed3ad | ||
|
6aaead1d4a | ||
|
ffc928242b | ||
|
f54244b7d0 | ||
|
3ba33ccd99 | ||
|
e302fed6cf | ||
|
9e4b6c197d | ||
|
a9f787fd76 | ||
|
f6d50f8cc5 | ||
|
388366542d | ||
|
575af30d88 | ||
|
85d24d180e | ||
|
11454b802e | ||
|
364ef6c5fe | ||
|
1466c9f984 | ||
|
dcdca90dd0 | ||
|
4241179471 | ||
|
71882863a5 | ||
|
44e6bb6f7a | ||
|
2a3460827d | ||
|
1e0c582b98 | ||
|
539119c57d | ||
|
77de6d90bf | ||
|
995ab18e7b | ||
|
a7340eae1a | ||
|
0bf4b3ef8c | ||
|
c3e57efa9d | ||
|
8dbad9a8d4 | ||
|
c27c1906aa | ||
|
249b1a92e2 | ||
|
14d89a3cfa | ||
|
d44262d820 | ||
|
5936c1ecef | ||
|
5fdbd52303 | ||
|
e18de43407 |
98 changed files with 2611 additions and 2631 deletions
6
.git-blame-ignore-revs
Normal file
6
.git-blame-ignore-revs
Normal file
|
@ -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
|
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
|
@ -9,3 +9,7 @@ updates:
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
|
groups:
|
||||||
|
ci:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
179
.github/workflows/ansible-test.yml
vendored
179
.github/workflows/ansible-test.yml
vendored
|
@ -1,179 +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.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
|
|
||||||
- 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: >-
|
|
||||||
${{ contains(fromJson(
|
|
||||||
'["stable-2.9", "stable-2.10", "stable-2.11"]'
|
|
||||||
), matrix.ansible) && 'ubuntu-20.04' || '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-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
|
|
||||||
|
|
||||||
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: >-
|
|
||||||
${{ contains(fromJson(
|
|
||||||
'["stable-2.9", "stable-2.10", "stable-2.11"]'
|
|
||||||
), 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
|
|
||||||
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
|
|
||||||
- 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.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
|
|
||||||
# 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:
|
|
||||||
# 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"]'
|
|
||||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
|
||||||
name: I (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }})
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
ansible:
|
|
||||||
- devel
|
|
||||||
python:
|
|
||||||
- "3.10"
|
|
||||||
- "3.11"
|
|
||||||
- "3.12"
|
|
||||||
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"
|
|
||||||
# 2.16
|
|
||||||
- ansible: stable-2.16
|
|
||||||
python: "3.10"
|
|
||||||
# 2.17
|
|
||||||
- ansible: stable-2.17
|
|
||||||
python: "3.7"
|
|
||||||
# 2.18
|
|
||||||
- ansible: stable-2.18
|
|
||||||
python: "3.8"
|
|
||||||
|
|
||||||
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.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'
|
|
||||||
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
|
|
||||||
target-python-version: ${{ matrix.python }}
|
|
||||||
testing-type: integration
|
|
2
.github/workflows/docs-pr.yml
vendored
2
.github/workflows/docs-pr.yml
vendored
|
@ -7,7 +7,7 @@ name: Collection Docs
|
||||||
concurrency:
|
concurrency:
|
||||||
group: docs-pr-${{ github.head_ref }}
|
group: docs-pr-${{ github.head_ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
on:
|
'on':
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened, synchronize, reopened, closed]
|
types: [opened, synchronize, reopened, closed]
|
||||||
|
|
||||||
|
|
2
.github/workflows/docs-push.yml
vendored
2
.github/workflows/docs-push.yml
vendored
|
@ -7,7 +7,7 @@ name: Collection Docs
|
||||||
concurrency:
|
concurrency:
|
||||||
group: docs-push-${{ github.sha }}
|
group: docs-push-${{ github.sha }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
on:
|
'on':
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
163
.github/workflows/ee.yml
vendored
163
.github/workflows/ee.yml
vendored
|
@ -1,163 +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: '"#"'
|
|
||||||
- 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
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
path: ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }}
|
|
||||||
|
|
||||||
- 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 "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)"
|
|
||||||
|
|
||||||
# EE config
|
|
||||||
cat > execution-environment.yml <<EOF
|
|
||||||
---
|
|
||||||
version: 3
|
|
||||||
dependencies:
|
|
||||||
ansible_core:
|
|
||||||
package_pip: ${{ matrix.ansible_core }}
|
|
||||||
ansible_runner:
|
|
||||||
package_pip: ${{ matrix.ansible_runner }}
|
|
||||||
galaxy: requirements.yml
|
|
||||||
${{ matrix.other_deps }}
|
|
||||||
|
|
||||||
images:
|
|
||||||
base_image:
|
|
||||||
name: ${{ matrix.base_image }}
|
|
||||||
|
|
||||||
additional_build_files:
|
|
||||||
- src: ${COLLECTION_FILENAME}
|
|
||||||
dest: src
|
|
||||||
|
|
||||||
additional_build_steps:
|
|
||||||
prepend_base:
|
|
||||||
- ${{ matrix.pre_base }}
|
|
||||||
EOF
|
|
||||||
echo "::group::execution-environment.yml"
|
|
||||||
cat execution-environment.yml
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# Requirements
|
|
||||||
cat > requirements.yml <<EOF
|
|
||||||
---
|
|
||||||
collections:
|
|
||||||
- name: src/${COLLECTION_FILENAME}
|
|
||||||
type: file
|
|
||||||
EOF
|
|
||||||
echo "::group::requirements.yml"
|
|
||||||
cat requirements.yml
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
- name: Build image based on ${{ matrix.base_image }}
|
|
||||||
run: |
|
|
||||||
ansible-builder build --verbosity 3 --tag test-ee:latest --container-runtime docker
|
|
||||||
|
|
||||||
- name: Show images
|
|
||||||
run: docker image ls
|
|
||||||
|
|
||||||
- name: Run basic tests
|
|
||||||
run: >
|
|
||||||
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
|
|
51
.github/workflows/extra-tests.yml
vendored
51
.github/workflows/extra-tests.yml
vendored
|
@ -1,51 +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}}
|
|
||||||
|
|
||||||
- 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}}
|
|
20
.github/workflows/import-galaxy.yml
vendored
20
.github/workflows/import-galaxy.yml
vendored
|
@ -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
|
|
35
.github/workflows/nox.yml
vendored
Normal file
35
.github/workflows/nox.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
# 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: nox
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
pull_request:
|
||||||
|
# Run CI once per day (at 05:15 UTC)
|
||||||
|
schedule:
|
||||||
|
- cron: '15 5 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nox:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: "Run extra sanity tests"
|
||||||
|
steps:
|
||||||
|
- name: Check out collection
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Run nox
|
||||||
|
uses: ansible-community/antsibull-nox@main
|
||||||
|
|
||||||
|
ansible-test:
|
||||||
|
uses: ansible-community/antsibull-nox/.github/workflows/reusable-nox-matrix.yml@main
|
||||||
|
with:
|
||||||
|
upload-codecov: true
|
||||||
|
secrets:
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
27
.github/workflows/reuse.yml
vendored
27
.github/workflows/reuse.yml
vendored
|
@ -1,27 +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: Verify REUSE
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
# Run CI once per day (at 05:15 UTC)
|
|
||||||
schedule:
|
|
||||||
- cron: '15 5 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: REUSE Compliance Check
|
|
||||||
uses: fsfe/reuse-action@v4
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/tests/output/
|
/tests/output/
|
||||||
/changelogs/.plugin-cache.yaml
|
/changelogs/.plugin-cache.yaml
|
||||||
|
/tests/integration/inventory
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|
|
@ -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
|
|
53
.yamllint
Normal file
53
.yamllint
Normal file
|
@ -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 <felix@fontein.de>
|
||||||
|
|
||||||
|
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
|
54
.yamllint-docs
Normal file
54
.yamllint-docs
Normal file
|
@ -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 <felix@fontein.de>
|
||||||
|
|
||||||
|
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
|
54
.yamllint-examples
Normal file
54
.yamllint-examples
Normal file
|
@ -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 <felix@fontein.de>
|
||||||
|
|
||||||
|
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
|
53
.yamllint-extra-docs
Normal file
53
.yamllint-extra-docs
Normal file
|
@ -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 <felix@fontein.de>
|
||||||
|
|
||||||
|
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
|
531
CHANGELOG.md
531
CHANGELOG.md
|
@ -2,135 +2,322 @@
|
||||||
|
|
||||||
**Topics**
|
**Topics**
|
||||||
|
|
||||||
- <a href="#v2-20-0">v2\.20\.0</a>
|
- <a href="#v3-8-1">v3\.8\.1</a>
|
||||||
- <a href="#release-summary">Release Summary</a>
|
- <a href="#release-summary">Release Summary</a>
|
||||||
- <a href="#minor-changes">Minor Changes</a>
|
|
||||||
- <a href="#v2-19-0">v2\.19\.0</a>
|
|
||||||
- <a href="#release-summary-1">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-1">Minor Changes</a>
|
|
||||||
- <a href="#v2-18-0">v2\.18\.0</a>
|
|
||||||
- <a href="#release-summary-2">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-2">Minor Changes</a>
|
|
||||||
- <a href="#deprecated-features">Deprecated Features</a>
|
|
||||||
- <a href="#bugfixes">Bugfixes</a>
|
- <a href="#bugfixes">Bugfixes</a>
|
||||||
- <a href="#v2-17-0">v2\.17\.0</a>
|
- <a href="#v3-8-0">v3\.8\.0</a>
|
||||||
|
- <a href="#release-summary-1">Release Summary</a>
|
||||||
|
- <a href="#minor-changes">Minor Changes</a>
|
||||||
|
- <a href="#v3-7-0">v3\.7\.0</a>
|
||||||
|
- <a href="#release-summary-2">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-1">Minor Changes</a>
|
||||||
|
- <a href="#v3-6-0">v3\.6\.0</a>
|
||||||
- <a href="#release-summary-3">Release Summary</a>
|
- <a href="#release-summary-3">Release Summary</a>
|
||||||
- <a href="#minor-changes-3">Minor Changes</a>
|
- <a href="#minor-changes-2">Minor Changes</a>
|
||||||
- <a href="#v2-16-0">v2\.16\.0</a>
|
- <a href="#v3-5-0">v3\.5\.0</a>
|
||||||
- <a href="#release-summary-4">Release Summary</a>
|
- <a href="#release-summary-4">Release Summary</a>
|
||||||
- <a href="#minor-changes-4">Minor Changes</a>
|
- <a href="#minor-changes-3">Minor Changes</a>
|
||||||
- <a href="#v2-15-0">v2\.15\.0</a>
|
- <a href="#v3-4-0">v3\.4\.0</a>
|
||||||
- <a href="#release-summary-5">Release Summary</a>
|
- <a href="#release-summary-5">Release Summary</a>
|
||||||
- <a href="#minor-changes-5">Minor Changes</a>
|
- <a href="#minor-changes-4">Minor Changes</a>
|
||||||
- <a href="#v2-14-0">v2\.14\.0</a>
|
|
||||||
- <a href="#release-summary-6">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-6">Minor Changes</a>
|
|
||||||
- <a href="#v2-13-0">v2\.13\.0</a>
|
|
||||||
- <a href="#release-summary-7">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-7">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-1">Bugfixes</a>
|
- <a href="#bugfixes-1">Bugfixes</a>
|
||||||
- <a href="#v2-12-0">v2\.12\.0</a>
|
- <a href="#v3-3-0">v3\.3\.0</a>
|
||||||
|
- <a href="#release-summary-6">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-5">Minor Changes</a>
|
||||||
|
- <a href="#v3-2-0">v3\.2\.0</a>
|
||||||
|
- <a href="#release-summary-7">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-6">Minor Changes</a>
|
||||||
|
- <a href="#v3-1-0">v3\.1\.0</a>
|
||||||
- <a href="#release-summary-8">Release Summary</a>
|
- <a href="#release-summary-8">Release Summary</a>
|
||||||
- <a href="#minor-changes-8">Minor Changes</a>
|
- <a href="#minor-changes-7">Minor Changes</a>
|
||||||
- <a href="#v2-11-0">v2\.11\.0</a>
|
|
||||||
- <a href="#release-summary-9">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-9">Minor Changes</a>
|
|
||||||
- <a href="#v2-10-0">v2\.10\.0</a>
|
|
||||||
- <a href="#release-summary-10">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-10">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-2">Bugfixes</a>
|
- <a href="#bugfixes-2">Bugfixes</a>
|
||||||
- <a href="#v2-9-0">v2\.9\.0</a>
|
- <a href="#v3-0-0">v3\.0\.0</a>
|
||||||
|
- <a href="#release-summary-9">Release Summary</a>
|
||||||
|
- <a href="#breaking-changes--porting-guide">Breaking Changes / Porting Guide</a>
|
||||||
|
- <a href="#removed-features-previously-deprecated">Removed Features \(previously deprecated\)</a>
|
||||||
|
- <a href="#v2-20-0">v2\.20\.0</a>
|
||||||
|
- <a href="#release-summary-10">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-8">Minor Changes</a>
|
||||||
|
- <a href="#v2-19-0">v2\.19\.0</a>
|
||||||
- <a href="#release-summary-11">Release Summary</a>
|
- <a href="#release-summary-11">Release Summary</a>
|
||||||
- <a href="#minor-changes-11">Minor Changes</a>
|
- <a href="#minor-changes-9">Minor Changes</a>
|
||||||
- <a href="#bugfixes-3">Bugfixes</a>
|
- <a href="#v2-18-0">v2\.18\.0</a>
|
||||||
- <a href="#v2-8-3">v2\.8\.3</a>
|
|
||||||
- <a href="#release-summary-12">Release Summary</a>
|
- <a href="#release-summary-12">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-10">Minor Changes</a>
|
||||||
|
- <a href="#deprecated-features">Deprecated Features</a>
|
||||||
|
- <a href="#bugfixes-3">Bugfixes</a>
|
||||||
|
- <a href="#v2-17-0">v2\.17\.0</a>
|
||||||
|
- <a href="#release-summary-13">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-11">Minor Changes</a>
|
||||||
|
- <a href="#v2-16-0">v2\.16\.0</a>
|
||||||
|
- <a href="#release-summary-14">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-12">Minor Changes</a>
|
||||||
|
- <a href="#v2-15-0">v2\.15\.0</a>
|
||||||
|
- <a href="#release-summary-15">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-13">Minor Changes</a>
|
||||||
|
- <a href="#v2-14-0">v2\.14\.0</a>
|
||||||
|
- <a href="#release-summary-16">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-14">Minor Changes</a>
|
||||||
|
- <a href="#v2-13-0">v2\.13\.0</a>
|
||||||
|
- <a href="#release-summary-17">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-15">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-4">Bugfixes</a>
|
||||||
|
- <a href="#v2-12-0">v2\.12\.0</a>
|
||||||
|
- <a href="#release-summary-18">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-16">Minor Changes</a>
|
||||||
|
- <a href="#v2-11-0">v2\.11\.0</a>
|
||||||
|
- <a href="#release-summary-19">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-17">Minor Changes</a>
|
||||||
|
- <a href="#v2-10-0">v2\.10\.0</a>
|
||||||
|
- <a href="#release-summary-20">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-18">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-5">Bugfixes</a>
|
||||||
|
- <a href="#v2-9-0">v2\.9\.0</a>
|
||||||
|
- <a href="#release-summary-21">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-19">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-6">Bugfixes</a>
|
||||||
|
- <a href="#v2-8-3">v2\.8\.3</a>
|
||||||
|
- <a href="#release-summary-22">Release Summary</a>
|
||||||
- <a href="#known-issues">Known Issues</a>
|
- <a href="#known-issues">Known Issues</a>
|
||||||
- <a href="#v2-8-2">v2\.8\.2</a>
|
- <a href="#v2-8-2">v2\.8\.2</a>
|
||||||
- <a href="#release-summary-13">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-4">Bugfixes</a>
|
|
||||||
- <a href="#v2-8-1">v2\.8\.1</a>
|
|
||||||
- <a href="#release-summary-14">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-5">Bugfixes</a>
|
|
||||||
- <a href="#v2-8-0">v2\.8\.0</a>
|
|
||||||
- <a href="#release-summary-15">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-12">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-6">Bugfixes</a>
|
|
||||||
- <a href="#v2-7-0">v2\.7\.0</a>
|
|
||||||
- <a href="#release-summary-16">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-13">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-7">Bugfixes</a>
|
|
||||||
- <a href="#v2-6-0">v2\.6\.0</a>
|
|
||||||
- <a href="#release-summary-17">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-14">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-8">Bugfixes</a>
|
|
||||||
- <a href="#v2-5-0">v2\.5\.0</a>
|
|
||||||
- <a href="#release-summary-18">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-15">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-9">Bugfixes</a>
|
|
||||||
- <a href="#v2-4-0">v2\.4\.0</a>
|
|
||||||
- <a href="#release-summary-19">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-16">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-10">Bugfixes</a>
|
|
||||||
- <a href="#known-issues-1">Known Issues</a>
|
|
||||||
- <a href="#v2-3-1">v2\.3\.1</a>
|
|
||||||
- <a href="#release-summary-20">Release Summary</a>
|
|
||||||
- <a href="#known-issues-2">Known Issues</a>
|
|
||||||
- <a href="#v2-3-0">v2\.3\.0</a>
|
|
||||||
- <a href="#release-summary-21">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-17">Minor Changes</a>
|
|
||||||
- <a href="#bugfixes-11">Bugfixes</a>
|
|
||||||
- <a href="#v2-2-1">v2\.2\.1</a>
|
|
||||||
- <a href="#release-summary-22">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-12">Bugfixes</a>
|
|
||||||
- <a href="#v2-2-0">v2\.2\.0</a>
|
|
||||||
- <a href="#release-summary-23">Release Summary</a>
|
- <a href="#release-summary-23">Release Summary</a>
|
||||||
- <a href="#minor-changes-18">Minor Changes</a>
|
- <a href="#bugfixes-7">Bugfixes</a>
|
||||||
- <a href="#bugfixes-13">Bugfixes</a>
|
- <a href="#v2-8-1">v2\.8\.1</a>
|
||||||
- <a href="#new-modules">New Modules</a>
|
|
||||||
- <a href="#v2-1-0">v2\.1\.0</a>
|
|
||||||
- <a href="#release-summary-24">Release Summary</a>
|
- <a href="#release-summary-24">Release Summary</a>
|
||||||
- <a href="#minor-changes-19">Minor Changes</a>
|
- <a href="#bugfixes-8">Bugfixes</a>
|
||||||
- <a href="#bugfixes-14">Bugfixes</a>
|
- <a href="#v2-8-0">v2\.8\.0</a>
|
||||||
- <a href="#new-modules-1">New Modules</a>
|
|
||||||
- <a href="#v2-0-0">v2\.0\.0</a>
|
|
||||||
- <a href="#release-summary-25">Release Summary</a>
|
- <a href="#release-summary-25">Release Summary</a>
|
||||||
- <a href="#minor-changes-20">Minor Changes</a>
|
- <a href="#minor-changes-20">Minor Changes</a>
|
||||||
- <a href="#breaking-changes--porting-guide">Breaking Changes / Porting Guide</a>
|
- <a href="#bugfixes-9">Bugfixes</a>
|
||||||
|
- <a href="#v2-7-0">v2\.7\.0</a>
|
||||||
|
- <a href="#release-summary-26">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-21">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-10">Bugfixes</a>
|
||||||
|
- <a href="#v2-6-0">v2\.6\.0</a>
|
||||||
|
- <a href="#release-summary-27">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-22">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-11">Bugfixes</a>
|
||||||
|
- <a href="#v2-5-0">v2\.5\.0</a>
|
||||||
|
- <a href="#release-summary-28">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-23">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-12">Bugfixes</a>
|
||||||
|
- <a href="#v2-4-0">v2\.4\.0</a>
|
||||||
|
- <a href="#release-summary-29">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-24">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-13">Bugfixes</a>
|
||||||
|
- <a href="#known-issues-1">Known Issues</a>
|
||||||
|
- <a href="#v2-3-1">v2\.3\.1</a>
|
||||||
|
- <a href="#release-summary-30">Release Summary</a>
|
||||||
|
- <a href="#known-issues-2">Known Issues</a>
|
||||||
|
- <a href="#v2-3-0">v2\.3\.0</a>
|
||||||
|
- <a href="#release-summary-31">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-25">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-14">Bugfixes</a>
|
||||||
|
- <a href="#v2-2-1">v2\.2\.1</a>
|
||||||
|
- <a href="#release-summary-32">Release Summary</a>
|
||||||
- <a href="#bugfixes-15">Bugfixes</a>
|
- <a href="#bugfixes-15">Bugfixes</a>
|
||||||
|
- <a href="#v2-2-0">v2\.2\.0</a>
|
||||||
|
- <a href="#release-summary-33">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-26">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-16">Bugfixes</a>
|
||||||
|
- <a href="#new-modules">New Modules</a>
|
||||||
|
- <a href="#v2-1-0">v2\.1\.0</a>
|
||||||
|
- <a href="#release-summary-34">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-27">Minor Changes</a>
|
||||||
|
- <a href="#bugfixes-17">Bugfixes</a>
|
||||||
|
- <a href="#new-modules-1">New Modules</a>
|
||||||
|
- <a href="#v2-0-0">v2\.0\.0</a>
|
||||||
|
- <a href="#release-summary-35">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-28">Minor Changes</a>
|
||||||
|
- <a href="#breaking-changes--porting-guide-1">Breaking Changes / Porting Guide</a>
|
||||||
|
- <a href="#bugfixes-18">Bugfixes</a>
|
||||||
- <a href="#new-plugins">New Plugins</a>
|
- <a href="#new-plugins">New Plugins</a>
|
||||||
- <a href="#filter">Filter</a>
|
- <a href="#filter">Filter</a>
|
||||||
- <a href="#v1-2-0">v1\.2\.0</a>
|
- <a href="#v1-2-0">v1\.2\.0</a>
|
||||||
- <a href="#release-summary-26">Release Summary</a>
|
- <a href="#release-summary-36">Release Summary</a>
|
||||||
- <a href="#minor-changes-21">Minor Changes</a>
|
- <a href="#minor-changes-29">Minor Changes</a>
|
||||||
- <a href="#bugfixes-16">Bugfixes</a>
|
|
||||||
- <a href="#v1-1-0">v1\.1\.0</a>
|
|
||||||
- <a href="#release-summary-27">Release Summary</a>
|
|
||||||
- <a href="#minor-changes-22">Minor Changes</a>
|
|
||||||
- <a href="#v1-0-1">v1\.0\.1</a>
|
|
||||||
- <a href="#release-summary-28">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-17">Bugfixes</a>
|
|
||||||
- <a href="#v1-0-0">v1\.0\.0</a>
|
|
||||||
- <a href="#release-summary-29">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-18">Bugfixes</a>
|
|
||||||
- <a href="#v0-1-1">v0\.1\.1</a>
|
|
||||||
- <a href="#release-summary-30">Release Summary</a>
|
|
||||||
- <a href="#bugfixes-19">Bugfixes</a>
|
- <a href="#bugfixes-19">Bugfixes</a>
|
||||||
|
- <a href="#v1-1-0">v1\.1\.0</a>
|
||||||
|
- <a href="#release-summary-37">Release Summary</a>
|
||||||
|
- <a href="#minor-changes-30">Minor Changes</a>
|
||||||
|
- <a href="#v1-0-1">v1\.0\.1</a>
|
||||||
|
- <a href="#release-summary-38">Release Summary</a>
|
||||||
|
- <a href="#bugfixes-20">Bugfixes</a>
|
||||||
|
- <a href="#v1-0-0">v1\.0\.0</a>
|
||||||
|
- <a href="#release-summary-39">Release Summary</a>
|
||||||
|
- <a href="#bugfixes-21">Bugfixes</a>
|
||||||
|
- <a href="#v0-1-1">v0\.1\.1</a>
|
||||||
|
- <a href="#release-summary-40">Release Summary</a>
|
||||||
|
- <a href="#bugfixes-22">Bugfixes</a>
|
||||||
- <a href="#v0-1-0">v0\.1\.0</a>
|
- <a href="#v0-1-0">v0\.1\.0</a>
|
||||||
- <a href="#release-summary-31">Release Summary</a>
|
- <a href="#release-summary-41">Release Summary</a>
|
||||||
- <a href="#minor-changes-23">Minor Changes</a>
|
- <a href="#minor-changes-31">Minor Changes</a>
|
||||||
|
|
||||||
<a id="v2-20-0"></a>
|
<a id="v3-8-1"></a>
|
||||||
## v2\.20\.0
|
## v3\.8\.1
|
||||||
|
|
||||||
<a id="release-summary"></a>
|
<a id="release-summary"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
|
Bugfix release\.
|
||||||
|
|
||||||
|
<a id="bugfixes"></a>
|
||||||
|
### 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)\)\.
|
||||||
|
|
||||||
|
<a id="v3-8-0"></a>
|
||||||
|
## v3\.8\.0
|
||||||
|
|
||||||
|
<a id="release-summary-1"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes"></a>
|
<a id="minor-changes"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add <code>interface ethernet switch port\-isolation</code> 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 <code>routing bfd configuration</code>\. 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 <code>ip ipsec mode\-config</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/376](https\://github\.com/ansible\-collections/community\.routeros/pull/376)\)\.
|
||||||
|
|
||||||
|
<a id="v3-7-0"></a>
|
||||||
|
## v3\.7\.0
|
||||||
|
|
||||||
|
<a id="release-summary-2"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-1"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_find\_and\_modify \- allow to control whether <code>dynamic</code> and/or <code>builtin</code> entries are ignored with the new <code>ignore\_dynamic</code> and <code>ignore\_builtin</code> 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 <code>port\-cost\-mode</code> to <code>interface bridge</code> 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)\)\.
|
||||||
|
|
||||||
|
<a id="v3-6-0"></a>
|
||||||
|
## v3\.6\.0
|
||||||
|
|
||||||
|
<a id="release-summary-3"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-2"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add <code>mdns\-repeat\-ifaces</code> to <code>ip dns</code> 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 <code>routing bgp connection</code> 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 <code>is\-responder</code> property in <code>interface wireguard peers</code> to <code>responder</code> for RouterOS 7\.17 and newer \([https\://github\.com/ansible\-collections/community\.routeros/pull/364](https\://github\.com/ansible\-collections/community\.routeros/pull/364)\)\.
|
||||||
|
|
||||||
|
<a id="v3-5-0"></a>
|
||||||
|
## v3\.5\.0
|
||||||
|
|
||||||
|
<a id="release-summary-4"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-3"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- change default for <code>/ip/cloud/ddns\-enabled</code> for RouterOS 7\.17 and newer from <code>yes</code> to <code>auto</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/350](https\://github\.com/ansible\-collections/community\.routeros/pull/350)\)\.
|
||||||
|
|
||||||
|
<a id="v3-4-0"></a>
|
||||||
|
## v3\.4\.0
|
||||||
|
|
||||||
|
<a id="release-summary-5"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature and bugfix release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-4"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add support for the <code>ip dns forwarders</code> 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)\)\.
|
||||||
|
|
||||||
|
<a id="bugfixes-1"></a>
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- remove the primary key <code>action</code> from the <code>interface wifi provisioning</code> 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)\)\.
|
||||||
|
|
||||||
|
<a id="v3-3-0"></a>
|
||||||
|
## v3\.3\.0
|
||||||
|
|
||||||
|
<a id="release-summary-6"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-5"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add missing attribute <code>require\-message\-auth</code> for the <code>radius</code> 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 <code>interface 6to4</code> 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 <code>interface wireless access\-list</code> and <code>interface wireless connect\-list</code> 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 <code>use\-interface\-duid</code> option for <code>ipv6 dhcp\-client</code> 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 <code>script</code>\, <code>custom\-duid</code> and <code>validate\-server\-duid</code> 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)\)\.
|
||||||
|
|
||||||
|
<a id="v3-2-0"></a>
|
||||||
|
## v3\.2\.0
|
||||||
|
|
||||||
|
<a id="release-summary-7"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-6"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add support for the <code>routing filter community\-list</code> 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)\)\.
|
||||||
|
|
||||||
|
<a id="v3-1-0"></a>
|
||||||
|
## v3\.1\.0
|
||||||
|
|
||||||
|
<a id="release-summary-8"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Bugfix and feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-7"></a>
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- add missing fields <code>comment</code>\, <code>next\-pool</code> to <code>ip pool</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/327](https\://github\.com/ansible\-collections/community\.routeros/pull/327)\)\.
|
||||||
|
|
||||||
|
<a id="bugfixes-2"></a>
|
||||||
|
### Bugfixes
|
||||||
|
|
||||||
|
* api\_info\, api\_modify \- fields <code>log</code> and <code>log\-prefix</code> in paths <code>ip firewall filter</code>\, <code>ip firewall mangle</code>\, <code>ip firewall nat</code>\, <code>ip firewall raw</code> now have the correct default values \([https\://github\.com/ansible\-collections/community\.routeros/pull/324](https\://github\.com/ansible\-collections/community\.routeros/pull/324)\)\.
|
||||||
|
|
||||||
|
<a id="v3-0-0"></a>
|
||||||
|
## v3\.0\.0
|
||||||
|
|
||||||
|
<a id="release-summary-9"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Major release that drops support for End of Life Python versions and fixes check mode for community\.routeros\.command\.
|
||||||
|
|
||||||
|
<a id="breaking-changes--porting-guide"></a>
|
||||||
|
### 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)\)\.
|
||||||
|
|
||||||
|
<a id="removed-features-previously-deprecated"></a>
|
||||||
|
### 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)\)\.
|
||||||
|
|
||||||
|
<a id="v2-20-0"></a>
|
||||||
|
## v2\.20\.0
|
||||||
|
|
||||||
|
<a id="release-summary-10"></a>
|
||||||
|
### Release Summary
|
||||||
|
|
||||||
|
Feature release\.
|
||||||
|
|
||||||
|
<a id="minor-changes-8"></a>
|
||||||
|
### 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 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 <code>interface l2tp\-client</code> 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 <code>interface l2tp\-client</code> 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 <code>cpu\-frequency</code>\, <code>memory\-frequency</code>\, <code>preboot\-etherboot</code> and <code>preboot\-etherboot\-server</code> properties in <code>system routerboard settings</code> \([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 <code>cpu\-frequency</code>\, <code>memory\-frequency</code>\, <code>preboot\-etherboot</code> and <code>preboot\-etherboot\-server</code> properties in <code>system routerboard settings</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/320](https\://github\.com/ansible\-collections/community\.routeros/pull/320)\)\.
|
||||||
|
@ -139,12 +326,12 @@ Feature release\.
|
||||||
<a id="v2-19-0"></a>
|
<a id="v2-19-0"></a>
|
||||||
## v2\.19\.0
|
## v2\.19\.0
|
||||||
|
|
||||||
<a id="release-summary-1"></a>
|
<a id="release-summary-11"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-1"></a>
|
<a id="minor-changes-9"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add support for the <code>ip dns adlist</code> 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 <code>ip dns adlist</code> 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)\)\.
|
||||||
|
@ -156,12 +343,12 @@ Feature release\.
|
||||||
<a id="v2-18-0"></a>
|
<a id="v2-18-0"></a>
|
||||||
## v2\.18\.0
|
## v2\.18\.0
|
||||||
|
|
||||||
<a id="release-summary-2"></a>
|
<a id="release-summary-12"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-2"></a>
|
<a id="minor-changes-10"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info \- allow to restrict the output by limiting fields to specific values with the new <code>restrict</code> option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\.
|
* api\_info \- allow to restrict the output by limiting fields to specific values with the new <code>restrict</code> option \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\.
|
||||||
|
@ -177,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\.
|
* 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\.
|
||||||
|
|
||||||
<a id="bugfixes"></a>
|
<a id="bugfixes-3"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- change the default of <code>ingress\-filtering</code> in paths <code>interface bridge</code> and <code>interface bridge port</code> back to <code>false</code> for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\.
|
* api\_modify\, api\_info \- change the default of <code>ingress\-filtering</code> in paths <code>interface bridge</code> and <code>interface bridge port</code> back to <code>false</code> for RouterOS before version 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/305](https\://github\.com/ansible\-collections/community\.routeros/pull/305)\)\.
|
||||||
|
@ -185,12 +372,12 @@ Feature release\.
|
||||||
<a id="v2-17-0"></a>
|
<a id="v2-17-0"></a>
|
||||||
## v2\.17\.0
|
## v2\.17\.0
|
||||||
|
|
||||||
<a id="release-summary-3"></a>
|
<a id="release-summary-13"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-3"></a>
|
<a id="minor-changes-11"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add <code>system health settings</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\.
|
* api\_info\, api\_modify \- add <code>system health settings</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/294](https\://github\.com/ansible\-collections/community\.routeros/pull/294)\)\.
|
||||||
|
@ -200,12 +387,12 @@ Feature release\.
|
||||||
<a id="v2-16-0"></a>
|
<a id="v2-16-0"></a>
|
||||||
## v2\.16\.0
|
## v2\.16\.0
|
||||||
|
|
||||||
<a id="release-summary-4"></a>
|
<a id="release-summary-14"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-4"></a>
|
<a id="minor-changes-12"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add missing path <code>/ppp secret</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\.
|
* api\_info\, api\_modify \- add missing path <code>/ppp secret</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/286](https\://github\.com/ansible\-collections/community\.routeros/pull/286)\)\.
|
||||||
|
@ -214,12 +401,12 @@ Feature release\.
|
||||||
<a id="v2-15-0"></a>
|
<a id="v2-15-0"></a>
|
||||||
## v2\.15\.0
|
## v2\.15\.0
|
||||||
|
|
||||||
<a id="release-summary-5"></a>
|
<a id="release-summary-15"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-5"></a>
|
<a id="minor-changes-13"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- Add RouterOS 7\.x support to <code>/mpls ldp</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\.
|
* api\_info\, api\_modify \- Add RouterOS 7\.x support to <code>/mpls ldp</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/271](https\://github\.com/ansible\-collections/community\.routeros/pull/271)\)\.
|
||||||
|
@ -236,12 +423,12 @@ Feature release\.
|
||||||
<a id="v2-14-0"></a>
|
<a id="v2-14-0"></a>
|
||||||
## v2\.14\.0
|
## v2\.14\.0
|
||||||
|
|
||||||
<a id="release-summary-6"></a>
|
<a id="release-summary-16"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-6"></a>
|
<a id="minor-changes-14"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add read\-only fields <code>installed\-version</code>\, <code>latest\-version</code> and <code>status</code> in <code>system package update</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\.
|
* api\_info\, api\_modify \- add read\-only fields <code>installed\-version</code>\, <code>latest\-version</code> and <code>status</code> in <code>system package update</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/263](https\://github\.com/ansible\-collections/community\.routeros/pull/263)\)\.
|
||||||
|
@ -251,18 +438,18 @@ Feature release\.
|
||||||
<a id="v2-13-0"></a>
|
<a id="v2-13-0"></a>
|
||||||
## v2\.13\.0
|
## v2\.13\.0
|
||||||
|
|
||||||
<a id="release-summary-7"></a>
|
<a id="release-summary-17"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-7"></a>
|
<a id="minor-changes-15"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- make path <code>user group</code> modifiable and add <code>comment</code> 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\_info\, api\_modify \- make path <code>user group</code> modifiable and add <code>comment</code> 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 <code>ip vrf</code> path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\)
|
* api\_modify\, api\_info \- add support for the <code>ip vrf</code> path in RouterOS 7 \([https\://github\.com/ansible\-collections/community\.routeros/pull/259](https\://github\.com/ansible\-collections/community\.routeros/pull/259)\)
|
||||||
|
|
||||||
<a id="bugfixes-1"></a>
|
<a id="bugfixes-4"></a>
|
||||||
### Bugfixes
|
### 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)\)\.
|
* 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)\)\.
|
||||||
|
@ -270,12 +457,12 @@ Bugfix and feature release\.
|
||||||
<a id="v2-12-0"></a>
|
<a id="v2-12-0"></a>
|
||||||
## v2\.12\.0
|
## v2\.12\.0
|
||||||
|
|
||||||
<a id="release-summary-8"></a>
|
<a id="release-summary-18"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release\.
|
Feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-8"></a>
|
<a id="minor-changes-16"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add <code>interface ovpn\-client</code> 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 <code>interface ovpn\-client</code> 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)\)\.
|
||||||
|
@ -289,12 +476,12 @@ Feature release\.
|
||||||
<a id="v2-11-0"></a>
|
<a id="v2-11-0"></a>
|
||||||
## v2\.11\.0
|
## v2\.11\.0
|
||||||
|
|
||||||
<a id="release-summary-9"></a>
|
<a id="release-summary-19"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature and bugfix release\.
|
Feature and bugfix release\.
|
||||||
|
|
||||||
<a id="minor-changes-9"></a>
|
<a id="minor-changes-17"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add missing DoH parameters <code>doh\-max\-concurrent\-queries</code>\, <code>doh\-max\-server\-connections</code>\, and <code>doh\-timeout</code> to the <code>ip dns</code> 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 DoH parameters <code>doh\-max\-concurrent\-queries</code>\, <code>doh\-max\-server\-connections</code>\, and <code>doh\-timeout</code> to the <code>ip dns</code> 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)\)
|
||||||
|
@ -309,12 +496,12 @@ Feature and bugfix release\.
|
||||||
<a id="v2-10-0"></a>
|
<a id="v2-10-0"></a>
|
||||||
## v2\.10\.0
|
## v2\.10\.0
|
||||||
|
|
||||||
<a id="release-summary-10"></a>
|
<a id="release-summary-20"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-10"></a>
|
<a id="minor-changes-18"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info \- add new <code>include\_read\_only</code> 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 \- add new <code>include\_read\_only</code> 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)\)\.
|
||||||
|
@ -338,7 +525,7 @@ Bugfix and feature release\.
|
||||||
* api\_modify \- add new <code>handle\_read\_only</code> and <code>handle\_write\_only</code> 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 \- add new <code>handle\_read\_only</code> and <code>handle\_write\_only</code> 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 <code>routing id</code>\, <code>routing bgp connection</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\.
|
* api\_modify\, api\_info \- support API paths <code>routing id</code>\, <code>routing bgp connection</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/220](https\://github\.com/ansible\-collections/community\.routeros/pull/220)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-2"></a>
|
<a id="bugfixes-5"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- in the <code>snmp</code> path\, ensure that <code>engine\-id\-suffix</code> is only available on RouterOS 7\.10\+\, and that <code>engine\-id</code> 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)\)\.
|
* api\_info\, api\_modify \- in the <code>snmp</code> path\, ensure that <code>engine\-id\-suffix</code> is only available on RouterOS 7\.10\+\, and that <code>engine\-id</code> 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)\)\.
|
||||||
|
@ -346,18 +533,18 @@ Bugfix and feature release\.
|
||||||
<a id="v2-9-0"></a>
|
<a id="v2-9-0"></a>
|
||||||
## v2\.9\.0
|
## v2\.9\.0
|
||||||
|
|
||||||
<a id="release-summary-11"></a>
|
<a id="release-summary-21"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-11"></a>
|
<a id="minor-changes-19"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- add path <code>caps\-man channel</code> and enable path <code>caps\-man manager interface</code> \([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 <code>caps\-man channel</code> and enable path <code>caps\-man manager interface</code> \([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 <code>ip traffic\-flow target</code> \([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)\)\.
|
* api\_info\, api\_modify \- add path <code>ip traffic\-flow target</code> \([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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-3"></a>
|
<a id="bugfixes-6"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- add missing parameter <code>engine\-id\-suffix</code> for the <code>snmp</code> 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)\)\.
|
* api\_modify\, api\_info \- add missing parameter <code>engine\-id\-suffix</code> for the <code>snmp</code> 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)\)\.
|
||||||
|
@ -365,7 +552,7 @@ Bugfix and feature release\.
|
||||||
<a id="v2-8-3"></a>
|
<a id="v2-8-3"></a>
|
||||||
## v2\.8\.3
|
## v2\.8\.3
|
||||||
|
|
||||||
<a id="release-summary-12"></a>
|
<a id="release-summary-22"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Maintenance release with updated documentation\.
|
Maintenance release with updated documentation\.
|
||||||
|
@ -386,12 +573,12 @@ for the rendered HTML version of the documentation of the latest release\.
|
||||||
<a id="v2-8-2"></a>
|
<a id="v2-8-2"></a>
|
||||||
## v2\.8\.2
|
## v2\.8\.2
|
||||||
|
|
||||||
<a id="release-summary-13"></a>
|
<a id="release-summary-23"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix release\.
|
Bugfix release\.
|
||||||
|
|
||||||
<a id="bugfixes-4"></a>
|
<a id="bugfixes-7"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- add missing parameter <code>tls</code> for the <code>tool e\-mail</code> 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)\)\.
|
* api\_modify\, api\_info \- add missing parameter <code>tls</code> for the <code>tool e\-mail</code> 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)\)\.
|
||||||
|
@ -399,12 +586,12 @@ Bugfix release\.
|
||||||
<a id="v2-8-1"></a>
|
<a id="v2-8-1"></a>
|
||||||
## v2\.8\.1
|
## v2\.8\.1
|
||||||
|
|
||||||
<a id="release-summary-14"></a>
|
<a id="release-summary-24"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix release\.
|
Bugfix release\.
|
||||||
|
|
||||||
<a id="bugfixes-5"></a>
|
<a id="bugfixes-8"></a>
|
||||||
### Bugfixes
|
### 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)\)\.
|
* 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)\)\.
|
||||||
|
@ -412,12 +599,12 @@ Bugfix release\.
|
||||||
<a id="v2-8-0"></a>
|
<a id="v2-8-0"></a>
|
||||||
## v2\.8\.0
|
## v2\.8\.0
|
||||||
|
|
||||||
<a id="release-summary-15"></a>
|
<a id="release-summary-25"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-12"></a>
|
<a id="minor-changes-20"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_modify \- adapt data for API paths <code>ip dhcp\-server network</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\.
|
* api\_modify \- adapt data for API paths <code>ip dhcp\-server network</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/156](https\://github\.com/ansible\-collections/community\.routeros/pull/156)\)\.
|
||||||
|
@ -427,7 +614,7 @@ Bugfix and feature release\.
|
||||||
* api\_modify \- support API paths <code>ip firewall layer7\-protocol</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/153](https\://github\.com/ansible\-collections/community\.routeros/pull/153)\)\.
|
* api\_modify \- support API paths <code>ip firewall layer7\-protocol</code> \([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)\)\.
|
* 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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-6"></a>
|
<a id="bugfixes-9"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- fix default and remove behavior for <code>dhcp\-options</code> in path <code>ip dhcp\-client</code> \([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\_info\, api\_modify \- fix default and remove behavior for <code>dhcp\-options</code> in path <code>ip dhcp\-client</code> \([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)\)\.
|
||||||
|
@ -437,17 +624,17 @@ Bugfix and feature release\.
|
||||||
<a id="v2-7-0"></a>
|
<a id="v2-7-0"></a>
|
||||||
## v2\.7\.0
|
## v2\.7\.0
|
||||||
|
|
||||||
<a id="release-summary-16"></a>
|
<a id="release-summary-26"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-13"></a>
|
<a id="minor-changes-21"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- support API paths <code>ip arp</code>\, <code>ip firewall raw</code>\, <code>ipv6 firewall raw</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\.
|
* api\_modify\, api\_info \- support API paths <code>ip arp</code>\, <code>ip firewall raw</code>\, <code>ipv6 firewall raw</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-7"></a>
|
<a id="bugfixes-10"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- defaults corrected for fields in <code>interface wireguard peers</code> API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\.
|
* api\_modify\, api\_info \- defaults corrected for fields in <code>interface wireguard peers</code> API path \([https\://github\.com/ansible\-collections/community\.routeros/pull/144](https\://github\.com/ansible\-collections/community\.routeros/pull/144)\)\.
|
||||||
|
@ -455,18 +642,18 @@ Bugfix and feature release\.
|
||||||
<a id="v2-6-0"></a>
|
<a id="v2-6-0"></a>
|
||||||
## v2\.6\.0
|
## v2\.6\.0
|
||||||
|
|
||||||
<a id="release-summary-17"></a>
|
<a id="release-summary-27"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Regular bugfix and feature release\.
|
Regular bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-14"></a>
|
<a id="minor-changes-22"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- add field <code>regexp</code> to <code>ip dns static</code> \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\.
|
* api\_modify\, api\_info \- add field <code>regexp</code> to <code>ip dns static</code> \([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 <code>interface wireguard</code>\, <code>interface wireguard peers</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\.
|
* api\_modify\, api\_info \- support API paths <code>interface wireguard</code>\, <code>interface wireguard peers</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/143](https\://github\.com/ansible\-collections/community\.routeros/pull/143)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-8"></a>
|
<a id="bugfixes-11"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify \- do not use <code>name</code> as a unique key in <code>ip dns static</code> \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\.
|
* api\_modify \- do not use <code>name</code> as a unique key in <code>ip dns static</code> \([https\://github\.com/ansible\-collections/community\.routeros/issues/141](https\://github\.com/ansible\-collections/community\.routeros/issues/141)\)\.
|
||||||
|
@ -475,17 +662,17 @@ Regular bugfix and feature release\.
|
||||||
<a id="v2-5-0"></a>
|
<a id="v2-5-0"></a>
|
||||||
## v2\.5\.0
|
## v2\.5\.0
|
||||||
|
|
||||||
<a id="release-summary-18"></a>
|
<a id="release-summary-28"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature and bugfix release\.
|
Feature and bugfix release\.
|
||||||
|
|
||||||
<a id="minor-changes-15"></a>
|
<a id="minor-changes-23"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\_info\, api\_modify \- support API paths <code>interface ethernet poe</code>\, <code>interface gre6</code>\, <code>interface vrrp</code> and also support all previously missing fields of entries in <code>ip dhcp\-server</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\.
|
* api\_info\, api\_modify \- support API paths <code>interface ethernet poe</code>\, <code>interface gre6</code>\, <code>interface vrrp</code> and also support all previously missing fields of entries in <code>ip dhcp\-server</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-9"></a>
|
<a id="bugfixes-12"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify \- <code>address\-pool</code> field of entries in API path <code>ip dhcp\-server</code> is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\.
|
* api\_modify \- <code>address\-pool</code> field of entries in API path <code>ip dhcp\-server</code> is not required anymore \([https\://github\.com/ansible\-collections/community\.routeros/pull/137](https\://github\.com/ansible\-collections/community\.routeros/pull/137)\)\.
|
||||||
|
@ -493,12 +680,12 @@ Feature and bugfix release\.
|
||||||
<a id="v2-4-0"></a>
|
<a id="v2-4-0"></a>
|
||||||
## v2\.4\.0
|
## v2\.4\.0
|
||||||
|
|
||||||
<a id="release-summary-19"></a>
|
<a id="release-summary-29"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature release improving the <code>api\*</code> modules\.
|
Feature release improving the <code>api\*</code> modules\.
|
||||||
|
|
||||||
<a id="minor-changes-16"></a>
|
<a id="minor-changes-24"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api\* modules \- Add new option <code>force\_no\_cert</code> to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\.
|
* api\* modules \- Add new option <code>force\_no\_cert</code> to connect with ADH ciphers \([https\://github\.com/ansible\-collections/community\.routeros/pull/124](https\://github\.com/ansible\-collections/community\.routeros/pull/124)\)\.
|
||||||
|
@ -519,7 +706,7 @@ Feature release improving the <code>api\*</code> modules\.
|
||||||
* api\_modify\, api\_info \- support for fields <code>blackhole</code>\, <code>pref\-src</code>\, <code>routing\-table</code>\, <code>suppress\-hw\-offload</code>\, <code>type</code>\, <code>vrf\-interface</code> in <code>ip route</code> path \([https\://github\.com/ansible\-collections/community\.routeros/pull/131](https\://github\.com/ansible\-collections/community\.routeros/pull/131)\)\.
|
* api\_modify\, api\_info \- support for fields <code>blackhole</code>\, <code>pref\-src</code>\, <code>routing\-table</code>\, <code>suppress\-hw\-offload</code>\, <code>type</code>\, <code>vrf\-interface</code> in <code>ip route</code> 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 <code>system ntp client servers</code> and <code>system ntp server</code> available in ROS7\, as well as new fields <code>servers</code>\, <code>mode</code>\, and <code>vrf</code> for <code>system ntp client</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\.
|
* api\_modify\, api\_info \- support paths <code>system ntp client servers</code> and <code>system ntp server</code> available in ROS7\, as well as new fields <code>servers</code>\, <code>mode</code>\, and <code>vrf</code> for <code>system ntp client</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/122](https\://github\.com/ansible\-collections/community\.routeros/pull/122)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-10"></a>
|
<a id="bugfixes-13"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify \- <code>ip route</code> entry can be defined without the need of <code>gateway</code> 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 \- <code>ip route</code> entry can be defined without the need of <code>gateway</code> 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)\)\.
|
||||||
|
@ -537,7 +724,7 @@ Feature release improving the <code>api\*</code> modules\.
|
||||||
<a id="v2-3-1"></a>
|
<a id="v2-3-1"></a>
|
||||||
## v2\.3\.1
|
## v2\.3\.1
|
||||||
|
|
||||||
<a id="release-summary-20"></a>
|
<a id="release-summary-30"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Maintenance release with improved documentation\.
|
Maintenance release with improved documentation\.
|
||||||
|
@ -550,19 +737,19 @@ Maintenance release with improved documentation\.
|
||||||
<a id="v2-3-0"></a>
|
<a id="v2-3-0"></a>
|
||||||
## v2\.3\.0
|
## v2\.3\.0
|
||||||
|
|
||||||
<a id="release-summary-21"></a>
|
<a id="release-summary-31"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature and bugfix release\.
|
Feature and bugfix release\.
|
||||||
|
|
||||||
<a id="minor-changes-17"></a>
|
<a id="minor-changes-25"></a>
|
||||||
### Minor Changes
|
### 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)\)\.
|
* 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 <code>timeout</code> parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/109](https\://github\.com/ansible\-collections/community\.routeros/pull/109)\)\.
|
* api\* modules \- added <code>timeout</code> 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 <code>ip firewall mangle</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\.
|
* api\_modify\, api\_info \- support API path <code>ip firewall mangle</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-11"></a>
|
<a id="bugfixes-14"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- make API path <code>ip dhcp\-server</code> support <code>script</code>\, and <code>ip firewall nat</code> support <code>in\-interface</code> and <code>in\-interface\-list</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\.
|
* api\_modify\, api\_info \- make API path <code>ip dhcp\-server</code> support <code>script</code>\, and <code>ip firewall nat</code> support <code>in\-interface</code> and <code>in\-interface\-list</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/110](https\://github\.com/ansible\-collections/community\.routeros/pull/110)\)\.
|
||||||
|
@ -570,12 +757,12 @@ Feature and bugfix release\.
|
||||||
<a id="v2-2-1"></a>
|
<a id="v2-2-1"></a>
|
||||||
## v2\.2\.1
|
## v2\.2\.1
|
||||||
|
|
||||||
<a id="release-summary-22"></a>
|
<a id="release-summary-32"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix release\.
|
Bugfix release\.
|
||||||
|
|
||||||
<a id="bugfixes-12"></a>
|
<a id="bugfixes-15"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api\_modify\, api\_info \- make API path <code>ip dhcp\-server lease</code> support <code>server\=all</code> \([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 <code>ip dhcp\-server lease</code> support <code>server\=all</code> \([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)\)\.
|
||||||
|
@ -584,17 +771,17 @@ Bugfix release\.
|
||||||
<a id="v2-2-0"></a>
|
<a id="v2-2-0"></a>
|
||||||
## v2\.2\.0
|
## v2\.2\.0
|
||||||
|
|
||||||
<a id="release-summary-23"></a>
|
<a id="release-summary-33"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
New feature release\.
|
New feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-18"></a>
|
<a id="minor-changes-26"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* All software licenses are now in the <code>LICENSES/</code> directory of the collection root\. Moreover\, <code>SPDX\-License\-Identifier\:</code> 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)\)\.
|
* All software licenses are now in the <code>LICENSES/</code> directory of the collection root\. Moreover\, <code>SPDX\-License\-Identifier\:</code> 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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-13"></a>
|
<a id="bugfixes-16"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* Include <code>LICENSES/BSD\-2\-Clause\.txt</code> file for the <code>routeros</code> module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\.
|
* Include <code>LICENSES/BSD\-2\-Clause\.txt</code> file for the <code>routeros</code> module utils \([https\://github\.com/ansible\-collections/community\.routeros/pull/101](https\://github\.com/ansible\-collections/community\.routeros/pull/101)\)\.
|
||||||
|
@ -608,12 +795,12 @@ New feature release\.
|
||||||
<a id="v2-1-0"></a>
|
<a id="v2-1-0"></a>
|
||||||
## v2\.1\.0
|
## v2\.1\.0
|
||||||
|
|
||||||
<a id="release-summary-24"></a>
|
<a id="release-summary-34"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Feature and bugfix release with new modules\.
|
Feature and bugfix release with new modules\.
|
||||||
|
|
||||||
<a id="minor-changes-19"></a>
|
<a id="minor-changes-27"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* Added a <code>community\.routeros\.api</code> module defaults group\. Use with <code>group/community\.routeros\.api</code> 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)\)\.
|
* Added a <code>community\.routeros\.api</code> module defaults group\. Use with <code>group/community\.routeros\.api</code> 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)\)\.
|
||||||
|
@ -622,7 +809,7 @@ Feature and bugfix release with new modules\.
|
||||||
* api \- update <code>query</code> to accept symbolic parameters \([https\://github\.com/ansible\-collections/community\.routeros/pull/63](https\://github\.com/ansible\-collections/community\.routeros/pull/63)\)\.
|
* api \- update <code>query</code> 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)\)\.
|
* 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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-14"></a>
|
<a id="bugfixes-17"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* query \- fix query function check for <code>\.id</code> vs\. <code>id</code> arguments to not conflict with routeros arguments like <code>identity</code> \([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)\)\.
|
* query \- fix query function check for <code>\.id</code> vs\. <code>id</code> arguments to not conflict with routeros arguments like <code>identity</code> \([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)\)\.
|
||||||
|
@ -637,26 +824,26 @@ Feature and bugfix release with new modules\.
|
||||||
<a id="v2-0-0"></a>
|
<a id="v2-0-0"></a>
|
||||||
## v2\.0\.0
|
## v2\.0\.0
|
||||||
|
|
||||||
<a id="release-summary-25"></a>
|
<a id="release-summary-35"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
A new major release with breaking changes in the behavior of <code>community\.routeros\.api</code> and <code>community\.routeros\.command</code>\.
|
A new major release with breaking changes in the behavior of <code>community\.routeros\.api</code> and <code>community\.routeros\.command</code>\.
|
||||||
|
|
||||||
<a id="minor-changes-20"></a>
|
<a id="minor-changes-28"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* api \- make validation of <code>WHERE</code> for <code>query</code> more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\.
|
* api \- make validation of <code>WHERE</code> for <code>query</code> more strict \([https\://github\.com/ansible\-collections/community\.routeros/pull/53](https\://github\.com/ansible\-collections/community\.routeros/pull/53)\)\.
|
||||||
* command \- the <code>commands</code> and <code>wait\_for</code> 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)\)\.
|
* command \- the <code>commands</code> and <code>wait\_for</code> 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 <code>gather\_subset</code> 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)\)\.
|
* facts \- the <code>gather\_subset</code> 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)\)\.
|
||||||
|
|
||||||
<a id="breaking-changes--porting-guide"></a>
|
<a id="breaking-changes--porting-guide-1"></a>
|
||||||
### Breaking Changes / Porting Guide
|
### 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 <code>failure\: already have such address</code>\)\, you need to adjust your roles/playbooks\. We suggest to use <code>failed\_when</code> to accept failure in specific circumstances\, for example <code>failed\_when\: \"\'failure\: already have \' in result\.msg\[0\]\"</code> \([https\://github\.com/ansible\-collections/community\.routeros/pull/39](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 <code>failure\: already have such address</code>\)\, you need to adjust your roles/playbooks\. We suggest to use <code>failed\_when</code> to accept failure in specific circumstances\, for example <code>failed\_when\: \"\'failure\: already have \' in result\.msg\[0\]\"</code> \([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)\)\.
|
* 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 <code>changed\_when</code> 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)\)\.
|
* command \- the module now always indicates that a change happens\. If this is not correct\, please use <code>changed\_when</code> 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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-15"></a>
|
<a id="bugfixes-18"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api \- improve splitting of <code>WHERE</code> queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\.
|
* api \- improve splitting of <code>WHERE</code> queries \([https\://github\.com/ansible\-collections/community\.routeros/pull/47](https\://github\.com/ansible\-collections/community\.routeros/pull/47)\)\.
|
||||||
|
@ -678,12 +865,12 @@ A new major release with breaking changes in the behavior of <code>community\.ro
|
||||||
<a id="v1-2-0"></a>
|
<a id="v1-2-0"></a>
|
||||||
## v1\.2\.0
|
## v1\.2\.0
|
||||||
|
|
||||||
<a id="release-summary-26"></a>
|
<a id="release-summary-36"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Bugfix and feature release\.
|
Bugfix and feature release\.
|
||||||
|
|
||||||
<a id="minor-changes-21"></a>
|
<a id="minor-changes-29"></a>
|
||||||
### Minor Changes
|
### 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)\)\.
|
* 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)\)\.
|
||||||
|
@ -691,7 +878,7 @@ Bugfix and feature release\.
|
||||||
* api \- rename option <code>ssl</code> to <code>tls</code>\, 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)\)\.
|
* api \- rename option <code>ssl</code> to <code>tls</code>\, 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 <code>ansible\_net\_config\_nonverbose</code> 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)\)\.
|
* fact \- add fact <code>ansible\_net\_config\_nonverbose</code> 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)\)\.
|
||||||
|
|
||||||
<a id="bugfixes-16"></a>
|
<a id="bugfixes-19"></a>
|
||||||
### Bugfixes
|
### 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)\)\.
|
* 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)\)\.
|
||||||
|
@ -699,12 +886,12 @@ Bugfix and feature release\.
|
||||||
<a id="v1-1-0"></a>
|
<a id="v1-1-0"></a>
|
||||||
## v1\.1\.0
|
## v1\.1\.0
|
||||||
|
|
||||||
<a id="release-summary-27"></a>
|
<a id="release-summary-37"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
This release allow dashes in usernames for SSH\-based modules\.
|
This release allow dashes in usernames for SSH\-based modules\.
|
||||||
|
|
||||||
<a id="minor-changes-22"></a>
|
<a id="minor-changes-30"></a>
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|
||||||
* command \- added support for a dash \(<code>\-</code>\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\.
|
* command \- added support for a dash \(<code>\-</code>\) in username \([https\://github\.com/ansible\-collections/community\.routeros/pull/18](https\://github\.com/ansible\-collections/community\.routeros/pull/18)\)\.
|
||||||
|
@ -713,12 +900,12 @@ This release allow dashes in usernames for SSH\-based modules\.
|
||||||
<a id="v1-0-1"></a>
|
<a id="v1-0-1"></a>
|
||||||
## v1\.0\.1
|
## v1\.0\.1
|
||||||
|
|
||||||
<a id="release-summary-28"></a>
|
<a id="release-summary-38"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Maintenance release with a bugfix for <code>api</code>\.
|
Maintenance release with a bugfix for <code>api</code>\.
|
||||||
|
|
||||||
<a id="bugfixes-17"></a>
|
<a id="bugfixes-20"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api \- remove <code>id to \.id</code> as default requirement which conflicts with RouterOS <code>id</code> configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\.
|
* api \- remove <code>id to \.id</code> as default requirement which conflicts with RouterOS <code>id</code> configuration parameter \([https\://github\.com/ansible\-collections/community\.routeros/pull/15](https\://github\.com/ansible\-collections/community\.routeros/pull/15)\)\.
|
||||||
|
@ -726,12 +913,12 @@ Maintenance release with a bugfix for <code>api</code>\.
|
||||||
<a id="v1-0-0"></a>
|
<a id="v1-0-0"></a>
|
||||||
## v1\.0\.0
|
## v1\.0\.0
|
||||||
|
|
||||||
<a id="release-summary-29"></a>
|
<a id="release-summary-39"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
This is the first production \(non\-prerelease\) release of <code>community\.routeros</code>\.
|
This is the first production \(non\-prerelease\) release of <code>community\.routeros</code>\.
|
||||||
|
|
||||||
<a id="bugfixes-18"></a>
|
<a id="bugfixes-21"></a>
|
||||||
### Bugfixes
|
### 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)\)\.
|
* 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)\)\.
|
||||||
|
@ -739,12 +926,12 @@ This is the first production \(non\-prerelease\) release of <code>community\.rou
|
||||||
<a id="v0-1-1"></a>
|
<a id="v0-1-1"></a>
|
||||||
## v0\.1\.1
|
## v0\.1\.1
|
||||||
|
|
||||||
<a id="release-summary-30"></a>
|
<a id="release-summary-40"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
Small improvements and bugfixes over the initial release\.
|
Small improvements and bugfixes over the initial release\.
|
||||||
|
|
||||||
<a id="bugfixes-19"></a>
|
<a id="bugfixes-22"></a>
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
* api \- fix crash when the <code>ssl</code> parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\.
|
* api \- fix crash when the <code>ssl</code> parameter is used \([https\://github\.com/ansible\-collections/community\.routeros/pull/3](https\://github\.com/ansible\-collections/community\.routeros/pull/3)\)\.
|
||||||
|
@ -752,12 +939,12 @@ Small improvements and bugfixes over the initial release\.
|
||||||
<a id="v0-1-0"></a>
|
<a id="v0-1-0"></a>
|
||||||
## v0\.1\.0
|
## v0\.1\.0
|
||||||
|
|
||||||
<a id="release-summary-31"></a>
|
<a id="release-summary-41"></a>
|
||||||
### Release Summary
|
### Release Summary
|
||||||
|
|
||||||
The <code>community\.routeros</code> continues the work on the Ansible RouterOS modules from their state in <code>community\.network</code> 1\.2\.0\. The changes listed here are thus relative to the modules <code>community\.network\.routeros\_\*</code>\.
|
The <code>community\.routeros</code> continues the work on the Ansible RouterOS modules from their state in <code>community\.network</code> 1\.2\.0\. The changes listed here are thus relative to the modules <code>community\.network\.routeros\_\*</code>\.
|
||||||
|
|
||||||
<a id="minor-changes-23"></a>
|
<a id="minor-changes-31"></a>
|
||||||
### Minor Changes
|
### 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 \- 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)\)\.
|
||||||
|
|
154
CHANGELOG.rst
154
CHANGELOG.rst
|
@ -4,6 +4,160 @@ Community RouterOS Release Notes
|
||||||
|
|
||||||
.. contents:: Topics
|
.. 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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
||||||
|
======
|
||||||
|
|
||||||
|
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
|
v2.20.0
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|
|
@ -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.
|
|
|
@ -5,7 +5,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Community RouterOS Collection
|
# Community RouterOS Collection
|
||||||
[](https://github.com/ansible-collections/community.routeros/actions)
|
[](https://docs.ansible.com/ansible/devel/collections/community/routeros/)
|
||||||
|
[](https://github.com/ansible-collections/community.routeros/actions)
|
||||||
[](https://codecov.io/gh/ansible-collections/community.routeros)
|
[](https://codecov.io/gh/ansible-collections/community.routeros)
|
||||||
[](https://api.reuse.software/info/github.com/ansible-collections/community.routeros)
|
[](https://api.reuse.software/info/github.com/ansible-collections/community.routeros)
|
||||||
|
|
||||||
|
@ -33,11 +34,11 @@ For more information about communication, see the [Ansible communication guide](
|
||||||
|
|
||||||
## Tested with Ansible
|
## 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, 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
|
## 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
|
### Supported connections
|
||||||
|
|
||||||
|
@ -207,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).
|
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/).
|
||||||
|
|
11
REUSE.toml
Normal file
11
REUSE.toml
Normal file
|
@ -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"
|
97
antsibull-nox.toml
Normal file
97
antsibull-nox.toml
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# 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]
|
||||||
|
run_isort = false
|
||||||
|
run_black = false
|
||||||
|
run_flake8 = false
|
||||||
|
run_pylint = false
|
||||||
|
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]
|
||||||
|
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]
|
||||||
|
|
||||||
|
[sessions.extra_checks]
|
||||||
|
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/",
|
||||||
|
]
|
||||||
|
run_avoid_characters = true
|
||||||
|
|
||||||
|
[[sessions.extra_checks.action_groups_config]]
|
||||||
|
name = "api"
|
||||||
|
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
|
||||||
|
|
||||||
|
[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"]
|
||||||
|
"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.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]]
|
||||||
|
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"}
|
|
@ -795,3 +795,152 @@ releases:
|
||||||
- 322-add-l2tp-client-interface-configuration.yml
|
- 322-add-l2tp-client-interface-configuration.yml
|
||||||
- 323-add-ros-7.16-parameters.yml
|
- 323-add-ros-7.16-parameters.yml
|
||||||
release_date: '2024-10-17'
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
|
|
@ -7,9 +7,9 @@ changelog_filename_template: ../CHANGELOG.rst
|
||||||
changelog_filename_version_depth: 0
|
changelog_filename_version_depth: 0
|
||||||
changes_file: changelog.yaml
|
changes_file: changelog.yaml
|
||||||
changes_format: combined
|
changes_format: combined
|
||||||
|
ignore_other_fragment_extensions: true
|
||||||
keep_fragments: false
|
keep_fragments: false
|
||||||
mention_ancestor: true
|
mention_ancestor: true
|
||||||
flatmap: true
|
|
||||||
new_plugins_after_name: removed_features
|
new_plugins_after_name: removed_features
|
||||||
notesdir: fragments
|
notesdir: fragments
|
||||||
output_formats:
|
output_formats:
|
||||||
|
@ -40,3 +40,4 @@ use_fqcn: true
|
||||||
add_plugin_period: true
|
add_plugin_period: true
|
||||||
changelog_nice_yaml: true
|
changelog_nice_yaml: true
|
||||||
changelog_sort: version
|
changelog_sort: version
|
||||||
|
vcs: auto
|
||||||
|
|
1
changelogs/fragments/3.9.0.yml
Normal file
1
changelogs/fragments/3.9.0.yml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
release_summary: Feature release.
|
3
changelogs/fragments/380-ipv6-settings.yml
Normal file
3
changelogs/fragments/380-ipv6-settings.yml
Normal file
|
@ -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).
|
2
changelogs/fragments/381-logging-cef.yml
Normal file
2
changelogs/fragments/381-logging-cef.yml
Normal file
|
@ -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).
|
2
changelogs/fragments/382-mangle-passthrough.yml
Normal file
2
changelogs/fragments/382-mangle-passthrough.yml
Normal file
|
@ -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).
|
7
changelogs/fragments/385-vrf-support-for-ovpn-server.yml
Normal file
7
changelogs/fragments/385-vrf-support-for-ovpn-server.yml
Normal file
|
@ -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).
|
|
@ -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).
|
|
@ -57,7 +57,7 @@ This results in the following output:
|
||||||
}
|
}
|
||||||
|
|
||||||
PLAY RECAP *******************************************************************************************************
|
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 <community.routeros.api#module>` for details on the options.
|
Check out the documentation of the :ansplugin:`community.routeros.api module <community.routeros.api#module>` for details on the options.
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ When this playbook completed successfully, you should be able to use the HTTPS a
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
- community.routeros.api:
|
- community.routeros.api:
|
||||||
...
|
# ...
|
||||||
tls: true
|
tls: true
|
||||||
validate_certs: true
|
validate_certs: true
|
||||||
validate_cert_hostname: true
|
validate_cert_hostname: true
|
||||||
|
|
|
@ -66,22 +66,22 @@ With the above inventory, you can use the following playbook to execute ``/syste
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
tasks:
|
tasks:
|
||||||
|
|
||||||
- name: Gather system resources
|
- name: Gather system resources
|
||||||
community.routeros.command:
|
community.routeros.command:
|
||||||
commands:
|
commands:
|
||||||
- /system resource print
|
- /system resource print
|
||||||
register: system_resource_print
|
register: system_resource_print
|
||||||
|
|
||||||
- name: Show system resources
|
- name: Show system resources
|
||||||
debug:
|
debug:
|
||||||
var: system_resource_print.stdout_lines
|
var: system_resource_print.stdout_lines
|
||||||
|
|
||||||
- name: Gather facts
|
- name: Gather facts
|
||||||
community.routeros.facts:
|
community.routeros.facts:
|
||||||
|
|
||||||
- name: Show a fact
|
- name: Show a fact
|
||||||
debug:
|
debug:
|
||||||
msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}"
|
msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}"
|
||||||
|
|
||||||
This results in the following output:
|
This results in the following output:
|
||||||
|
|
||||||
|
@ -126,4 +126,4 @@ This results in the following output:
|
||||||
}
|
}
|
||||||
|
|
||||||
PLAY RECAP *******************************************************************************************************
|
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
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace: community
|
namespace: community
|
||||||
name: routeros
|
name: routeros
|
||||||
version: 2.20.0
|
version: 3.9.0
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Egor Zaitsev (github.com/heuels)
|
- Egor Zaitsev (github.com/heuels)
|
||||||
|
@ -16,7 +16,7 @@ authors:
|
||||||
description: Modules and plugins for MikroTik RouterOS
|
description: Modules and plugins for MikroTik RouterOS
|
||||||
license:
|
license:
|
||||||
- GPL-3.0-or-later
|
- GPL-3.0-or-later
|
||||||
#license_file: COPYING
|
# license_file: COPYING
|
||||||
tags:
|
tags:
|
||||||
- network
|
- network
|
||||||
- mikrotik
|
- mikrotik
|
||||||
|
|
|
@ -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)
|
# 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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
requires_ansible: '>=2.9.10'
|
requires_ansible: '>=2.15.0'
|
||||||
action_groups:
|
action_groups:
|
||||||
api:
|
api:
|
||||||
- api
|
- api
|
||||||
|
|
53
noxfile.py
Normal file
53
noxfile.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# 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:
|
||||||
|
#
|
||||||
|
# /// 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()
|
|
@ -5,15 +5,14 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
author: "Egor Zaitsev (@heuels)"
|
author: "Egor Zaitsev (@heuels)"
|
||||||
name: routeros
|
name: routeros
|
||||||
short_description: Use routeros cliconf to run command on MikroTik RouterOS platform
|
short_description: Use routeros cliconf to run command on MikroTik RouterOS platform
|
||||||
description:
|
description:
|
||||||
- This routeros plugin provides low level abstraction apis for
|
- This routeros plugin provides low level abstraction APIs for sending and receiving CLI commands from MikroTik RouterOS
|
||||||
sending and receiving CLI commands from MikroTik RouterOS network devices.
|
network devices.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
|
|
@ -10,7 +10,7 @@ __metaclass__ = type
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
|
||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = r"""
|
||||||
options:
|
options:
|
||||||
hostname:
|
hostname:
|
||||||
description:
|
description:
|
||||||
|
@ -43,17 +43,16 @@ options:
|
||||||
- ssl
|
- ssl
|
||||||
port:
|
port:
|
||||||
description:
|
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.
|
- Defaults are V(8728) for the HTTP API, and V(8729) for the HTTPS API.
|
||||||
type: int
|
type: int
|
||||||
force_no_cert:
|
force_no_cert:
|
||||||
description:
|
description:
|
||||||
- Set to V(true) to connect without a certificate when O(tls=true).
|
- Set to V(true) to connect without a certificate when O(tls=true).
|
||||||
- See also O(validate_certs).
|
- See also O(validate_certs).
|
||||||
- B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible
|
- B(Note:) this forces the use of anonymous Diffie-Hellman (ADH) ciphers. The protocol is susceptible to Man-in-the-Middle
|
||||||
to Man-in-the-Middle attacks, because the keys used in the exchange are not authenticated.
|
attacks, because the keys used in the exchange are not authenticated. Instead of simply connecting without a certificate
|
||||||
Instead of simply connecting without a certificate to "make things work" have a look at
|
to "make things work" have a look at O(validate_certs) and O(ca_path).
|
||||||
O(validate_certs) and O(ca_path).
|
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
version_added: 2.4.0
|
version_added: 2.4.0
|
||||||
|
@ -61,10 +60,9 @@ options:
|
||||||
description:
|
description:
|
||||||
- Set to V(false) to skip validation of TLS certificates.
|
- Set to V(false) to skip validation of TLS certificates.
|
||||||
- See also O(validate_cert_hostname). Only used when O(tls=true).
|
- See also O(validate_cert_hostname). Only used when O(tls=true).
|
||||||
- B(Note:) instead of simply deactivating certificate validations to "make things work",
|
- B(Note:) instead of simply deactivating certificate validations to "make things work", please consider creating your
|
||||||
please consider creating your own CA certificate and using it to sign certificates used
|
own CA certificate and using it to sign certificates used for your router. You can tell the module about your CA certificate
|
||||||
for your router. You can tell the module about your CA certificate with the O(ca_path)
|
with the O(ca_path) option.
|
||||||
option.
|
|
||||||
type: bool
|
type: bool
|
||||||
default: true
|
default: true
|
||||||
version_added: 1.2.0
|
version_added: 1.2.0
|
||||||
|
@ -93,10 +91,10 @@ requirements:
|
||||||
- Python >= 3.6 (for librouteros)
|
- Python >= 3.6 (for librouteros)
|
||||||
seealso:
|
seealso:
|
||||||
- ref: ansible_collections.community.routeros.docsite.api-guide
|
- 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:
|
options:
|
||||||
restrict:
|
restrict:
|
||||||
type: list
|
type: list
|
||||||
|
@ -115,24 +113,21 @@ options:
|
||||||
values:
|
values:
|
||||||
description:
|
description:
|
||||||
- The values of the field to limit to.
|
- 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
|
||||||
Note that the types of the values are important. If you provide a string V("0"),
|
value returned by the API to the integer V(0), then this will not match. If you are not sure, better include both
|
||||||
and librouteros converts the value returned by the API to the integer V(0),
|
variants: both the string and the integer.'
|
||||||
then this will not match. If you are not sure, better include both variants:
|
|
||||||
both the string and the integer.
|
|
||||||
type: list
|
type: list
|
||||||
elements: raw
|
elements: raw
|
||||||
regex:
|
regex:
|
||||||
description:
|
description:
|
||||||
- A regular expression matching values of the field to limit to.
|
- A regular expression matching values of the field to limit to.
|
||||||
- Note that all values will be converted to strings before matching.
|
- Note that all values will be converted to strings before matching.
|
||||||
- It is not possible to match disabled values with regular expressions.
|
- It is not possible to match disabled values with regular expressions. Set O(restrict[].match_disabled=true) if
|
||||||
Set O(restrict[].match_disabled=true) if you also want to match disabled values.
|
you also want to match disabled values.
|
||||||
type: str
|
type: str
|
||||||
invert:
|
invert:
|
||||||
description:
|
description:
|
||||||
- Invert the condition. This affects O(restrict[].match_disabled), O(restrict[].values),
|
- Invert the condition. This affects O(restrict[].match_disabled), O(restrict[].values), and O(restrict[].regex).
|
||||||
and O(restrict[].regex).
|
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
'''
|
"""
|
||||||
|
|
|
@ -11,88 +11,102 @@ __metaclass__ = type
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
|
||||||
# Standard documentation fragment
|
# Standard documentation fragment
|
||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = r"""
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
description: Can run in C(check_mode) and return changed status prediction without modifying target.
|
description: Can run in C(check_mode) and return changed status prediction without modifying target.
|
||||||
diff_mode:
|
diff_mode:
|
||||||
description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode.
|
description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode.
|
||||||
platform:
|
platform:
|
||||||
description: Target OS/families that can be operated against.
|
description: Target OS/families that can be operated against.
|
||||||
support: N/A
|
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
|
# Should be used together with the standard fragment
|
||||||
INFO_MODULE = r'''
|
INFO_MODULE = r'''
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
support: full
|
support: full
|
||||||
details:
|
details:
|
||||||
- This action does not modify state.
|
- This action does not modify state.
|
||||||
diff_mode:
|
diff_mode:
|
||||||
support: N/A
|
support: N/A
|
||||||
details:
|
details:
|
||||||
- This action does not modify state.
|
- This action does not modify state.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
ACTIONGROUP_API = r'''
|
ACTIONGROUP_API = r'''
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
action_group:
|
action_group:
|
||||||
description: Use C(group/community.routeros.api) in C(module_defaults) to set defaults for this module.
|
description: Use C(group/community.routeros.api) in C(module_defaults) to set defaults for this module.
|
||||||
support: full
|
support: full
|
||||||
membership:
|
membership:
|
||||||
- community.routeros.api
|
- community.routeros.api
|
||||||
'''
|
'''
|
||||||
|
|
||||||
CONN = r'''
|
CONN = r"""
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
become:
|
become:
|
||||||
description: Is usable alongside C(become) keywords.
|
description: Is usable alongside C(become) keywords.
|
||||||
connection:
|
connection:
|
||||||
description: Uses the target's configured connection information to execute code on it.
|
description: Uses the target's configured connection information to execute code on it.
|
||||||
delegation:
|
delegation:
|
||||||
description: Can be used in conjunction with C(delegate_to) and related keywords.
|
description: Can be used in conjunction with C(delegate_to) and related keywords.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
FACTS = r'''
|
FACTS = r"""
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
facts:
|
facts:
|
||||||
description: Action returns an C(ansible_facts) dictionary that will update existing host 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
|
# Should be used together with the standard fragment and the FACTS fragment
|
||||||
FACTS_MODULE = r'''
|
FACTS_MODULE = r'''
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
support: full
|
support: full
|
||||||
details:
|
details:
|
||||||
- This action does not modify state.
|
- This action does not modify state.
|
||||||
diff_mode:
|
diff_mode:
|
||||||
support: N/A
|
support: N/A
|
||||||
details:
|
details:
|
||||||
- This action does not modify state.
|
- This action does not modify state.
|
||||||
facts:
|
facts:
|
||||||
support: full
|
support: full
|
||||||
'''
|
'''
|
||||||
|
|
||||||
FILES = r'''
|
FILES = r"""
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
safe_file_operations:
|
safe_file_operations:
|
||||||
description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption.
|
description: Uses Ansible's strict file operation functions to ensure proper permissions and avoid data corruption.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
FLOW = r'''
|
FLOW = r"""
|
||||||
options: {}
|
options: {}
|
||||||
attributes:
|
attributes:
|
||||||
action:
|
action:
|
||||||
description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller.
|
description: Indicates this has a corresponding action plugin so some parts of the options can be executed on the controller.
|
||||||
async:
|
async:
|
||||||
description: Supports being used with the C(async) keyword.
|
description: Supports being used with the C(async) keyword.
|
||||||
'''
|
"""
|
||||||
|
|
|
@ -20,6 +20,7 @@ DOCUMENTATION:
|
||||||
- Felix Fontein (@felixfontein)
|
- Felix Fontein (@felixfontein)
|
||||||
|
|
||||||
EXAMPLES: |
|
EXAMPLES: |
|
||||||
|
---
|
||||||
- name: Join arguments for a RouterOS CLI command
|
- name: Join arguments for a RouterOS CLI command
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
arguments: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.join }}"
|
arguments: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.join }}"
|
||||||
|
|
|
@ -30,6 +30,7 @@ DOCUMENTATION:
|
||||||
- Felix Fontein (@felixfontein)
|
- Felix Fontein (@felixfontein)
|
||||||
|
|
||||||
EXAMPLES: |
|
EXAMPLES: |
|
||||||
|
---
|
||||||
- name: Convert a list to a dictionary
|
- name: Convert a list to a dictionary
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
dictionary: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict }}"
|
dictionary: "{{ ['foo=bar', 'comment=foo is bar'] | community.routeros.list_to_dict }}"
|
||||||
|
|
|
@ -19,9 +19,11 @@ DOCUMENTATION:
|
||||||
- Felix Fontein (@felixfontein)
|
- Felix Fontein (@felixfontein)
|
||||||
|
|
||||||
EXAMPLES: |
|
EXAMPLES: |
|
||||||
|
---
|
||||||
- name: Quote a RouterOS CLI command argument
|
- name: Quote a RouterOS CLI command argument
|
||||||
ansible.builtin.set_fact:
|
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\""'
|
# Should result in 'comment="this is a \"comment\""'
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
|
|
|
@ -19,9 +19,11 @@ DOCUMENTATION:
|
||||||
- Felix Fontein (@felixfontein)
|
- Felix Fontein (@felixfontein)
|
||||||
|
|
||||||
EXAMPLES: |
|
EXAMPLES: |
|
||||||
|
---
|
||||||
- name: Quote a RouterOS CLI command argument's value
|
- name: Quote a RouterOS CLI command argument's value
|
||||||
ansible.builtin.set_fact:
|
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\""'
|
# Should result in '"this is a \"comment\""'
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
|
|
|
@ -19,9 +19,11 @@ DOCUMENTATION:
|
||||||
- Felix Fontein (@felixfontein)
|
- Felix Fontein (@felixfontein)
|
||||||
|
|
||||||
EXAMPLES: |
|
EXAMPLES: |
|
||||||
|
---
|
||||||
- name: Split command into list of arguments
|
- name: Split command into list of arguments
|
||||||
ansible.builtin.set_fact:
|
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']
|
# Should result in ['foo=bar', 'comment=foo is bar', 'baz']
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
|
|
|
@ -226,6 +226,25 @@ def join_path(path):
|
||||||
# 3. All bold attributes go into the `primary_keys` list -- this is not always true!
|
# 3. All bold attributes go into the `primary_keys` list -- this is not always true!
|
||||||
|
|
||||||
PATHS = {
|
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(
|
('interface', 'bonding'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
@ -262,6 +281,7 @@ PATHS = {
|
||||||
versioned_fields=[
|
versioned_fields=[
|
||||||
([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)),
|
([('7.0', '<')], 'ingress-filtering', KeyInfo(default=False)),
|
||||||
([('7.0', '>=')], 'ingress-filtering', KeyInfo(default=True)),
|
([('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', '>=')], 'forward-reserved-addresses', KeyInfo(default=False)),
|
||||||
([('7.16', '>=')], 'max-learned-entries', KeyInfo(default='auto')),
|
([('7.16', '>=')], 'max-learned-entries', KeyInfo(default='auto')),
|
||||||
],
|
],
|
||||||
|
@ -632,13 +652,22 @@ PATHS = {
|
||||||
),
|
),
|
||||||
('ip', 'ipsec', 'mode-config'): APIData(
|
('ip', 'ipsec', 'mode-config'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
unknown_mechanism=True,
|
fully_understood=True,
|
||||||
# primary_keys=('default', ),
|
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={
|
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(),
|
'name': KeyInfo(),
|
||||||
'responder': KeyInfo(),
|
'split-dns': KeyInfo(can_disable=True, remove_value=''),
|
||||||
'use-responder-dns': KeyInfo(),
|
'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),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -708,7 +737,9 @@ PATHS = {
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
primary_keys=('name', ),
|
primary_keys=('name', ),
|
||||||
fields={
|
fields={
|
||||||
|
'comment': KeyInfo(),
|
||||||
'name': KeyInfo(),
|
'name': KeyInfo(),
|
||||||
|
'next-pool': KeyInfo(),
|
||||||
'ranges': KeyInfo(),
|
'ranges': KeyInfo(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -893,6 +924,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(
|
('routing', 'ospf', 'instance'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
@ -1508,13 +1553,19 @@ PATHS = {
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
versioned_fields=[
|
versioned_fields=[
|
||||||
([('7.16', '>=')], 'multipath-hash-policy', KeyInfo(default='l3')),
|
([('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={
|
fields={
|
||||||
'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'),
|
'accept-redirects': KeyInfo(default='yes-if-forwarding-disabled'),
|
||||||
'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'),
|
'accept-router-advertisements': KeyInfo(default='yes-if-forwarding-disabled'),
|
||||||
'disable-ipv6': KeyInfo(default=False),
|
'disable-ipv6': KeyInfo(default=False),
|
||||||
'forward': KeyInfo(default=True),
|
'forward': KeyInfo(default=True),
|
||||||
'max-neighbor-entries': KeyInfo(default=8192),
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1613,23 +1664,46 @@ PATHS = {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('interface', 'ovpn-server', 'server'): APIData(
|
('interface', 'ovpn-server', 'server'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
versioned=[
|
||||||
single_value=True,
|
('7.17', '>=', VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
fields={
|
fields={
|
||||||
'auth': KeyInfo(),
|
'auth': KeyInfo(),
|
||||||
'cipher': KeyInfo(),
|
'cipher': KeyInfo(),
|
||||||
'default-profile': KeyInfo(default='default'),
|
'default-profile': KeyInfo(default='default'),
|
||||||
'enabled': KeyInfo(default=False),
|
'enabled': KeyInfo(default=False),
|
||||||
'keepalive-timeout': KeyInfo(default=60),
|
'keepalive-timeout': KeyInfo(default=60),
|
||||||
'mac-address': KeyInfo(),
|
'mac-address': KeyInfo(),
|
||||||
'max-mtu': KeyInfo(default=1500),
|
'max-mtu': KeyInfo(default=1500),
|
||||||
'mode': KeyInfo(default='ip'),
|
'mode': KeyInfo(default='ip'),
|
||||||
'netmask': KeyInfo(default=24),
|
'name': KeyInfo(default=''),
|
||||||
'port': KeyInfo(default=1194),
|
'netmask': KeyInfo(default=24),
|
||||||
'require-client-certificate': KeyInfo(default=False),
|
'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(
|
('interface', 'pppoe-server', 'server'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
|
@ -2002,7 +2076,6 @@ PATHS = {
|
||||||
versioned=[
|
versioned=[
|
||||||
('7.13', '>=', VersionedAPIData(
|
('7.13', '>=', VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
primary_keys=('action', ),
|
|
||||||
fields={
|
fields={
|
||||||
'action': KeyInfo(default='none'),
|
'action': KeyInfo(default='none'),
|
||||||
'address-ranges': KeyInfo(can_disable=True),
|
'address-ranges': KeyInfo(can_disable=True),
|
||||||
|
@ -2407,7 +2480,8 @@ PATHS = {
|
||||||
},
|
},
|
||||||
versioned_fields=[
|
versioned_fields=[
|
||||||
([('7.15', '>=')], 'name', KeyInfo()),
|
([('7.15', '>=')], 'name', KeyInfo()),
|
||||||
([('7.15', '>=')], 'is-responder', KeyInfo()),
|
([('7.15', '>='), ('7.17', '<')], 'is-responder', KeyInfo()),
|
||||||
|
([('7.17', '>=')], 'responder', KeyInfo()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2529,6 +2603,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(
|
('interface', 'wireless', 'cap'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
single_value=True,
|
single_value=True,
|
||||||
|
@ -2547,6 +2645,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(
|
('interface', 'wireless', 'security-profiles'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
@ -2684,8 +2817,11 @@ PATHS = {
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
single_value=True,
|
single_value=True,
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
versioned_fields=[
|
||||||
|
([('7.17', '<')], 'ddns-enabled', KeyInfo(default=False)),
|
||||||
|
([('7.17', '>=')], 'ddns-enabled', KeyInfo(default='auto')),
|
||||||
|
],
|
||||||
fields={
|
fields={
|
||||||
'ddns-enabled': KeyInfo(default=False),
|
|
||||||
'ddns-update-interval': KeyInfo(default='none'),
|
'ddns-update-interval': KeyInfo(default='none'),
|
||||||
'update-time': KeyInfo(default=True),
|
'update-time': KeyInfo(default=True),
|
||||||
},
|
},
|
||||||
|
@ -2871,6 +3007,7 @@ PATHS = {
|
||||||
([('7.8', '>=')], 'doh-max-concurrent-queries', KeyInfo(default=50)),
|
([('7.8', '>=')], 'doh-max-concurrent-queries', KeyInfo(default=50)),
|
||||||
([('7.8', '>=')], 'doh-max-server-connections', KeyInfo(default=5)),
|
([('7.8', '>=')], 'doh-max-server-connections', KeyInfo(default=5)),
|
||||||
([('7.8', '>=')], 'doh-timeout', KeyInfo(default='5s')),
|
([('7.8', '>=')], 'doh-timeout', KeyInfo(default='5s')),
|
||||||
|
([('7.16', '>=')], 'mdns-repeat-ifaces', KeyInfo()),
|
||||||
],
|
],
|
||||||
fields={
|
fields={
|
||||||
'allow-remote-requests': KeyInfo(),
|
'allow-remote-requests': KeyInfo(),
|
||||||
|
@ -2903,6 +3040,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(
|
('ip', 'dns', 'static'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
@ -2984,8 +3137,8 @@ PATHS = {
|
||||||
'jump-target': KeyInfo(can_disable=True),
|
'jump-target': KeyInfo(can_disable=True),
|
||||||
'layer7-protocol': KeyInfo(can_disable=True),
|
'layer7-protocol': KeyInfo(can_disable=True),
|
||||||
'limit': KeyInfo(can_disable=True),
|
'limit': KeyInfo(can_disable=True),
|
||||||
'log': KeyInfo(can_disable=True),
|
'log': KeyInfo(default=False),
|
||||||
'log-prefix': KeyInfo(can_disable=True),
|
'log-prefix': KeyInfo(default=''),
|
||||||
'nth': KeyInfo(can_disable=True),
|
'nth': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port': KeyInfo(can_disable=True),
|
'out-bridge-port': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port-list': KeyInfo(can_disable=True),
|
'out-bridge-port-list': KeyInfo(can_disable=True),
|
||||||
|
@ -3021,6 +3174,10 @@ PATHS = {
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
stratify_keys=('chain', ),
|
stratify_keys=('chain', ),
|
||||||
|
versioned_fields=[
|
||||||
|
([('7.19', '<')], 'passthrough', KeyInfo(can_disable=True)),
|
||||||
|
([('7.19', '>=')], 'passthrough', KeyInfo(default=True)),
|
||||||
|
],
|
||||||
fields={
|
fields={
|
||||||
'action': KeyInfo(),
|
'action': KeyInfo(),
|
||||||
'address-list': KeyInfo(can_disable=True),
|
'address-list': KeyInfo(can_disable=True),
|
||||||
|
@ -3055,8 +3212,8 @@ PATHS = {
|
||||||
'jump-target': KeyInfo(can_disable=True),
|
'jump-target': KeyInfo(can_disable=True),
|
||||||
'layer7-protocol': KeyInfo(can_disable=True),
|
'layer7-protocol': KeyInfo(can_disable=True),
|
||||||
'limit': KeyInfo(can_disable=True),
|
'limit': KeyInfo(can_disable=True),
|
||||||
'log': KeyInfo(can_disable=True),
|
'log': KeyInfo(default=False),
|
||||||
'log-prefix': KeyInfo(can_disable=True),
|
'log-prefix': KeyInfo(default=''),
|
||||||
'new-connection-mark': KeyInfo(can_disable=True),
|
'new-connection-mark': KeyInfo(can_disable=True),
|
||||||
'new-dscp': KeyInfo(can_disable=True),
|
'new-dscp': KeyInfo(can_disable=True),
|
||||||
'new-mss': KeyInfo(can_disable=True),
|
'new-mss': KeyInfo(can_disable=True),
|
||||||
|
@ -3072,7 +3229,6 @@ PATHS = {
|
||||||
'p2p': KeyInfo(can_disable=True),
|
'p2p': KeyInfo(can_disable=True),
|
||||||
'packet-mark': KeyInfo(can_disable=True),
|
'packet-mark': KeyInfo(can_disable=True),
|
||||||
'packet-size': KeyInfo(can_disable=True),
|
'packet-size': KeyInfo(can_disable=True),
|
||||||
'passthrough': KeyInfo(can_disable=True),
|
|
||||||
'per-connection-classifier': KeyInfo(can_disable=True),
|
'per-connection-classifier': KeyInfo(can_disable=True),
|
||||||
'port': KeyInfo(can_disable=True),
|
'port': KeyInfo(can_disable=True),
|
||||||
'priority': KeyInfo(can_disable=True),
|
'priority': KeyInfo(can_disable=True),
|
||||||
|
@ -3135,8 +3291,8 @@ PATHS = {
|
||||||
'jump-target': KeyInfo(can_disable=True),
|
'jump-target': KeyInfo(can_disable=True),
|
||||||
'layer7-protocol': KeyInfo(can_disable=True),
|
'layer7-protocol': KeyInfo(can_disable=True),
|
||||||
'limit': KeyInfo(can_disable=True),
|
'limit': KeyInfo(can_disable=True),
|
||||||
'log': KeyInfo(can_disable=True),
|
'log': KeyInfo(default=False),
|
||||||
'log-prefix': KeyInfo(can_disable=True),
|
'log-prefix': KeyInfo(default=''),
|
||||||
'nth': KeyInfo(can_disable=True),
|
'nth': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port': KeyInfo(can_disable=True),
|
'out-bridge-port': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port-list': KeyInfo(can_disable=True),
|
'out-bridge-port-list': KeyInfo(can_disable=True),
|
||||||
|
@ -3198,8 +3354,8 @@ PATHS = {
|
||||||
'ipv4-options': KeyInfo(can_disable=True),
|
'ipv4-options': KeyInfo(can_disable=True),
|
||||||
'jump-target': KeyInfo(can_disable=True),
|
'jump-target': KeyInfo(can_disable=True),
|
||||||
'limit': KeyInfo(can_disable=True),
|
'limit': KeyInfo(can_disable=True),
|
||||||
'log': KeyInfo(can_disable=True),
|
'log': KeyInfo(default=False),
|
||||||
'log-prefix': KeyInfo(can_disable=True),
|
'log-prefix': KeyInfo(default=''),
|
||||||
'nth': KeyInfo(can_disable=True),
|
'nth': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port': KeyInfo(can_disable=True),
|
'out-bridge-port': KeyInfo(can_disable=True),
|
||||||
'out-bridge-port-list': KeyInfo(can_disable=True),
|
'out-bridge-port-list': KeyInfo(can_disable=True),
|
||||||
|
@ -3469,6 +3625,14 @@ PATHS = {
|
||||||
'request': KeyInfo(),
|
'request': KeyInfo(),
|
||||||
'use-peer-dns': KeyInfo(default=True),
|
'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(
|
('ipv6', 'dhcp-server'): APIData(
|
||||||
|
@ -4002,6 +4166,9 @@ PATHS = {
|
||||||
'src-address': KeyInfo(default='0.0.0.0'),
|
'src-address': KeyInfo(default='0.0.0.0'),
|
||||||
'timeout': KeyInfo(default='300ms'),
|
'timeout': KeyInfo(default='300ms'),
|
||||||
},
|
},
|
||||||
|
versioned_fields=[
|
||||||
|
([('7.15', '>=')], 'require-message-auth', KeyInfo(default='yes-for-request-resp')),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('radius', 'incoming'): APIData(
|
('radius', 'incoming'): APIData(
|
||||||
|
@ -4052,6 +4219,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(
|
('routing', 'bfd', 'interface'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
unknown_mechanism=True,
|
unknown_mechanism=True,
|
||||||
|
@ -4768,6 +4957,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(
|
('ip', 'dhcp-client', 'option'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fixed_entries=True,
|
fixed_entries=True,
|
||||||
|
@ -4858,10 +5059,13 @@ PATHS = {
|
||||||
('routing', 'bgp', 'connection'): APIData(
|
('routing', 'bgp', 'connection'): APIData(
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
|
versioned_fields=[
|
||||||
|
([('7.19', '<')], 'address-families', KeyInfo()),
|
||||||
|
([('7.19', '>=')], 'afi', KeyInfo()),
|
||||||
|
],
|
||||||
fields={
|
fields={
|
||||||
'as': KeyInfo(),
|
'as': KeyInfo(),
|
||||||
'add-path-out': KeyInfo(),
|
'add-path-out': KeyInfo(),
|
||||||
'address-families': KeyInfo(),
|
|
||||||
'cisco-vpls-nlri-len-fmt': KeyInfo(),
|
'cisco-vpls-nlri-len-fmt': KeyInfo(),
|
||||||
'cluster-id': KeyInfo(),
|
'cluster-id': KeyInfo(),
|
||||||
'comment': KeyInfo(),
|
'comment': KeyInfo(),
|
||||||
|
@ -5040,6 +5244,11 @@ PATHS = {
|
||||||
unversioned=VersionedAPIData(
|
unversioned=VersionedAPIData(
|
||||||
fully_understood=True,
|
fully_understood=True,
|
||||||
primary_keys=('name',),
|
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={
|
fields={
|
||||||
'bsd-syslog': KeyInfo(default=False),
|
'bsd-syslog': KeyInfo(default=False),
|
||||||
'comment': KeyInfo(can_disable=True, remove_value=''),
|
'comment': KeyInfo(can_disable=True, remove_value=''),
|
||||||
|
@ -5142,7 +5351,7 @@ PATHS = {
|
||||||
'protocol': KeyInfo(default='all'),
|
'protocol': KeyInfo(default='all'),
|
||||||
'src-address': KeyInfo(),
|
'src-address': KeyInfo(),
|
||||||
'src-port': KeyInfo(default='any'),
|
'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
|
# created. This config captures the behavior best as it can
|
||||||
# i.e. template=yes is shown, template=no is hidden.
|
# i.e. template=yes is shown, template=no is hidden.
|
||||||
'template': KeyInfo(can_disable=True, remove_value=False),
|
'template': KeyInfo(can_disable=True, remove_value=False),
|
||||||
|
|
|
@ -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
|
|
|
@ -77,7 +77,7 @@ def _ros_api_connect(module, username, password, host, port, use_tls, force_no_c
|
||||||
elif not validate_cert_hostname:
|
elif not validate_cert_hostname:
|
||||||
ctx.check_hostname = False
|
ctx.check_hostname = False
|
||||||
else:
|
else:
|
||||||
# Since librouteros doesn't pass server_hostname,
|
# Since librouteros does not pass server_hostname,
|
||||||
# we have to do this ourselves:
|
# we have to do this ourselves:
|
||||||
def wrap_context(*args, **kwargs):
|
def wrap_context(*args, **kwargs):
|
||||||
kwargs.pop('server_hostname', None)
|
kwargs.pop('server_hostname', None)
|
||||||
|
|
|
@ -10,9 +10,4 @@ from __future__ import absolute_import, division, print_function
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can
|
from ansible.module_utils.compat.version import LooseVersion # pylint: disable=unused-import
|
||||||
# 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
|
|
||||||
|
|
|
@ -8,19 +8,17 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: api
|
module: api
|
||||||
author: "Nikolay Dachev (@NikolayDachev)"
|
author: "Nikolay Dachev (@NikolayDachev)"
|
||||||
short_description: Ansible module for RouterOS API
|
short_description: Ansible module for RouterOS API
|
||||||
description:
|
description:
|
||||||
- Ansible module for RouterOS API with the Python C(librouteros) library.
|
- 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:
|
notes:
|
||||||
- O(add), O(remove), O(update), O(cmd), and O(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
|
- Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules for more specific modifications,
|
||||||
for more specific modifications, and the M(community.routeros.api_info) module for a more controlled
|
and the M(community.routeros.api_info) module for a more controlled way of returning all entries for a path.
|
||||||
way of returning all entries for a path.
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.routeros.api
|
- community.routeros.api
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
|
@ -35,11 +33,15 @@ attributes:
|
||||||
platforms: RouterOS
|
platforms: RouterOS
|
||||||
action_group:
|
action_group:
|
||||||
version_added: 2.1.0
|
version_added: 2.1.0
|
||||||
|
idempotent:
|
||||||
|
support: N/A
|
||||||
|
details:
|
||||||
|
- Whether the executed command is idempotent depends on the operation performed.
|
||||||
options:
|
options:
|
||||||
path:
|
path:
|
||||||
description:
|
description:
|
||||||
- Main path for all other arguments.
|
- 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).
|
- Example V(ip address). Equivalent of RouterOS CLI C(/ip address print).
|
||||||
required: true
|
required: true
|
||||||
type: str
|
type: str
|
||||||
|
@ -59,20 +61,21 @@ options:
|
||||||
update:
|
update:
|
||||||
description:
|
description:
|
||||||
- Update config/value in RouterOS by '.id' in selected path.
|
- 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).
|
- 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).
|
- Note C(number) in RouterOS CLI is different from C(.id).
|
||||||
type: str
|
type: str
|
||||||
query:
|
query:
|
||||||
description:
|
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 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).
|
- 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) will return only C(.id) and C(address) for all items in V(ip address)
|
||||||
- Example path V(ip address) and query V(.id address WHERE address == 1.1.1.3/32).
|
path.
|
||||||
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(ip address) and query V(.id address WHERE address == 1.1.1.3/32). will return only C(.id) and C(address)
|
||||||
- Example path V(interface) and query V(mtu name WHERE mut > 1400) will
|
for items in V(ip address) path, where address is eq to 1.1.1.3/32.
|
||||||
return only interfaces C(mtu,name) where mtu is bigger than 1400.
|
- 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).
|
- Equivalent in RouterOS CLI C(/interface print where mtu > 1400).
|
||||||
type: str
|
type: str
|
||||||
extended_query:
|
extended_query:
|
||||||
|
@ -91,7 +94,8 @@ options:
|
||||||
where:
|
where:
|
||||||
description:
|
description:
|
||||||
- Allows to restrict the objects returned.
|
- 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
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
suboptions:
|
suboptions:
|
||||||
|
@ -105,7 +109,8 @@ options:
|
||||||
description:
|
description:
|
||||||
- The operator to use for matching.
|
- 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).
|
- 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),
|
- 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.
|
and O(extended_query.where[].value) have to be specified.
|
||||||
type: str
|
type: str
|
||||||
|
@ -133,7 +138,8 @@ options:
|
||||||
description:
|
description:
|
||||||
- The operator to use for matching.
|
- 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).
|
- 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
|
type: str
|
||||||
choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]
|
choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]
|
||||||
required: true
|
required: true
|
||||||
|
@ -150,14 +156,15 @@ options:
|
||||||
type: str
|
type: str
|
||||||
seealso:
|
seealso:
|
||||||
- ref: ansible_collections.community.routeros.docsite.quoting
|
- 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_facts
|
||||||
- module: community.routeros.api_find_and_modify
|
- module: community.routeros.api_find_and_modify
|
||||||
- module: community.routeros.api_info
|
- module: community.routeros.api_info
|
||||||
- module: community.routeros.api_modify
|
- module: community.routeros.api_modify
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = r"""
|
||||||
|
---
|
||||||
- name: Get example - ip address print
|
- name: Get example - ip address print
|
||||||
community.routeros.api:
|
community.routeros.api:
|
||||||
hostname: "{{ hostname }}"
|
hostname: "{{ hostname }}"
|
||||||
|
@ -216,8 +223,8 @@ EXAMPLES = '''
|
||||||
- attribute: "network"
|
- attribute: "network"
|
||||||
is: "in"
|
is: "in"
|
||||||
value:
|
value:
|
||||||
- "10.20.36.0"
|
- "10.20.36.0"
|
||||||
- "192.168.255.0"
|
- "192.168.255.0"
|
||||||
register: extended_queryout
|
register: extended_queryout
|
||||||
|
|
||||||
- name: Dump "Extended query example" output
|
- name: Dump "Extended query example" output
|
||||||
|
@ -231,9 +238,9 @@ EXAMPLES = '''
|
||||||
username: "{{ username }}"
|
username: "{{ username }}"
|
||||||
path: "ip address"
|
path: "ip address"
|
||||||
update: >-
|
update: >-
|
||||||
.id=*14
|
.id=*14
|
||||||
address=192.168.255.20/24
|
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 }}
|
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"
|
- name: Remove example - ether2 ip 192.168.255.20/24 with ".id = *14"
|
||||||
community.routeros.api:
|
community.routeros.api:
|
||||||
|
@ -255,18 +262,17 @@ EXAMPLES = '''
|
||||||
- name: Dump "Arbitrary command example" output
|
- name: Dump "Arbitrary command example" output
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: '{{ arbitraryout }}'
|
msg: '{{ arbitraryout }}'
|
||||||
'''
|
"""
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = r"""
|
||||||
---
|
|
||||||
message:
|
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:
|
sample:
|
||||||
- address: 1.2.3.4
|
- address: 1.2.3.4
|
||||||
- address: 2.3.4.5
|
- address: 2.3.4.5
|
||||||
type: list
|
type: list
|
||||||
returned: always
|
returned: always
|
||||||
'''
|
"""
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
|
@ -9,29 +9,27 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: api_facts
|
module: api_facts
|
||||||
author:
|
author:
|
||||||
- "Egor Zaitsev (@heuels)"
|
- "Egor Zaitsev (@heuels)"
|
||||||
- "Nikolay Dachev (@NikolayDachev)"
|
- "Nikolay Dachev (@NikolayDachev)"
|
||||||
- "Felix Fontein (@felixfontein)"
|
- "Felix Fontein (@felixfontein)"
|
||||||
version_added: 2.1.0
|
version_added: 2.1.0
|
||||||
short_description: Collect facts from remote devices running MikroTik RouterOS using the API
|
short_description: Collect facts from remote devices running MikroTik RouterOS using the API
|
||||||
description:
|
description:
|
||||||
- Collects a base set of device facts from a remote device that
|
- Collects a base set of device facts from a remote device that is running RouterOS. This module prepends all of the base
|
||||||
is running RouterOS. This module prepends all of the
|
network fact keys with C(ansible_net_<fact>). The facts module will always collect a base set of facts from the device
|
||||||
base network fact keys with C(ansible_net_<fact>). The facts
|
|
||||||
module will always collect a base set of facts from the device
|
|
||||||
and can enable or disable collection of additional facts.
|
and can enable or disable collection of additional facts.
|
||||||
- As opposed to the M(community.routeros.facts) module, it uses the
|
- As opposed to the M(community.routeros.facts) module, it uses the RouterOS API, similar to the M(community.routeros.api)
|
||||||
RouterOS API, similar to the M(community.routeros.api) module.
|
module.
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.routeros.api
|
- community.routeros.api
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
- community.routeros.attributes.actiongroup_api
|
- community.routeros.attributes.actiongroup_api
|
||||||
- community.routeros.attributes.facts
|
- community.routeros.attributes.facts
|
||||||
- community.routeros.attributes.facts_module
|
- community.routeros.attributes.facts_module
|
||||||
|
- community.routeros.attributes.idempotent_not_modify_state
|
||||||
attributes:
|
attributes:
|
||||||
platform:
|
platform:
|
||||||
support: full
|
support: full
|
||||||
|
@ -39,12 +37,10 @@ attributes:
|
||||||
options:
|
options:
|
||||||
gather_subset:
|
gather_subset:
|
||||||
description:
|
description:
|
||||||
- When supplied, this argument will restrict the facts collected
|
- When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument
|
||||||
to a given subset. Possible values for this argument include
|
include V(all), V(hardware), V(interfaces), and V(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 V(!) to specify that
|
||||||
- Can specify a list of values to include a larger subset.
|
a specific subset should not be collected.
|
||||||
Values can also be used with an initial V(!) to specify that a
|
|
||||||
specific subset should not be collected.
|
|
||||||
required: false
|
required: false
|
||||||
default:
|
default:
|
||||||
- all
|
- all
|
||||||
|
@ -56,9 +52,10 @@ seealso:
|
||||||
- module: community.routeros.api_find_and_modify
|
- module: community.routeros.api_find_and_modify
|
||||||
- module: community.routeros.api_info
|
- module: community.routeros.api_info
|
||||||
- module: community.routeros.api_modify
|
- module: community.routeros.api_modify
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = """
|
EXAMPLES = r"""
|
||||||
|
---
|
||||||
- name: Collect all facts from the device
|
- name: Collect all facts from the device
|
||||||
community.routeros.api_facts:
|
community.routeros.api_facts:
|
||||||
hostname: 192.168.88.1
|
hostname: 192.168.88.1
|
||||||
|
@ -75,7 +72,7 @@ EXAMPLES = """
|
||||||
- "!hardware"
|
- "!hardware"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = r"""
|
||||||
ansible_facts:
|
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
|
returned: always
|
||||||
|
@ -422,8 +419,6 @@ FACT_SUBSETS = dict(
|
||||||
|
|
||||||
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
|
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
|
||||||
|
|
||||||
warnings = []
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
|
@ -488,7 +483,7 @@ def main():
|
||||||
key = 'ansible_net_%s' % key
|
key = 'ansible_net_%s' % key
|
||||||
ansible_facts[key] = value
|
ansible_facts[key] = value
|
||||||
|
|
||||||
module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
|
module.exit_json(ansible_facts=ansible_facts)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: api_find_and_modify
|
module: api_find_and_modify
|
||||||
author:
|
author:
|
||||||
- "Felix Fontein (@felixfontein)"
|
- "Felix Fontein (@felixfontein)"
|
||||||
|
@ -17,13 +16,13 @@ short_description: Find and modify information using the API
|
||||||
version_added: 2.1.0
|
version_added: 2.1.0
|
||||||
description:
|
description:
|
||||||
- Allows to find entries for a path by conditions and modify the values of these entries.
|
- 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,
|
- Use the M(community.routeros.api_find_and_modify) module to set all entries of a path to specific values, or change multiple
|
||||||
or change multiple entries in different ways in one step.
|
entries in different ways in one step.
|
||||||
notes:
|
notes:
|
||||||
- "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that
|
- "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that there
|
||||||
there are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true).
|
are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true). This will make
|
||||||
This will make the module fail if there are less than N such entries, but not if there is no match. The latter case
|
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
|
||||||
is needed for idempotency of the task: once the values have been changed, there should be no further match."
|
of the task: once the values have been changed, there should be no further match."
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.routeros.api
|
- community.routeros.api
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
|
@ -36,6 +35,8 @@ attributes:
|
||||||
platform:
|
platform:
|
||||||
support: full
|
support: full
|
||||||
platforms: RouterOS
|
platforms: RouterOS
|
||||||
|
idempotent:
|
||||||
|
support: full
|
||||||
options:
|
options:
|
||||||
path:
|
path:
|
||||||
description:
|
description:
|
||||||
|
@ -74,14 +75,30 @@ options:
|
||||||
- Whether to allow that no match is found.
|
- 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.
|
- If not specified, this value is induced from whether O(require_matches_min) is 0 or larger.
|
||||||
type: bool
|
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:
|
seealso:
|
||||||
- module: community.routeros.api
|
- module: community.routeros.api
|
||||||
- module: community.routeros.api_facts
|
- module: community.routeros.api_facts
|
||||||
- module: community.routeros.api_modify
|
- module: community.routeros.api_modify
|
||||||
- module: community.routeros.api_info
|
- module: community.routeros.api_info
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = r"""
|
||||||
---
|
---
|
||||||
- name: Rename bridge from 'bridge' to 'my-bridge'
|
- name: Rename bridge from 'bridge' to 'my-bridge'
|
||||||
community.routeros.api_find_and_modify:
|
community.routeros.api_find_and_modify:
|
||||||
|
@ -93,6 +110,10 @@ EXAMPLES = '''
|
||||||
name: bridge
|
name: bridge
|
||||||
values:
|
values:
|
||||||
name: my-bridge
|
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
|
- name: Change IP address to 192.168.1.1 for interface bridge - assuming there is only one
|
||||||
community.routeros.api_find_and_modify:
|
community.routeros.api_find_and_modify:
|
||||||
|
@ -108,55 +129,58 @@ EXAMPLES = '''
|
||||||
# exactly one is configured.
|
# exactly one is configured.
|
||||||
require_matches_min: 1
|
require_matches_min: 1
|
||||||
require_matches_max: 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 = '''
|
RETURN = r"""
|
||||||
---
|
|
||||||
old_data:
|
old_data:
|
||||||
description:
|
description:
|
||||||
- A list of all elements for the current path before a change was made.
|
- A list of all elements for the current path before a change was made.
|
||||||
sample:
|
sample:
|
||||||
- '.id': '*1'
|
- '.id': '*1'
|
||||||
actual-interface: bridge
|
actual-interface: bridge
|
||||||
address: "192.168.88.1/24"
|
address: "192.168.88.1/24"
|
||||||
comment: defconf
|
comment: defconf
|
||||||
disabled: false
|
disabled: false
|
||||||
dynamic: false
|
dynamic: false
|
||||||
interface: bridge
|
interface: bridge
|
||||||
invalid: false
|
invalid: false
|
||||||
network: 192.168.88.0
|
network: 192.168.88.0
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
returned: success
|
returned: success
|
||||||
new_data:
|
new_data:
|
||||||
description:
|
description:
|
||||||
- A list of all elements for the current path after a change was made.
|
- A list of all elements for the current path after a change was made.
|
||||||
sample:
|
sample:
|
||||||
- '.id': '*1'
|
- '.id': '*1'
|
||||||
actual-interface: bridge
|
actual-interface: bridge
|
||||||
address: "192.168.1.1/24"
|
address: "192.168.1.1/24"
|
||||||
comment: awesome
|
comment: awesome
|
||||||
disabled: false
|
disabled: false
|
||||||
dynamic: false
|
dynamic: false
|
||||||
interface: bridge
|
interface: bridge
|
||||||
invalid: false
|
invalid: false
|
||||||
network: 192.168.1.0
|
network: 192.168.1.0
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
returned: success
|
returned: success
|
||||||
match_count:
|
match_count:
|
||||||
description:
|
description:
|
||||||
- The number of entries that matched the criteria in O(find).
|
- The number of entries that matched the criteria in O(find).
|
||||||
sample: 1
|
sample: 1
|
||||||
type: int
|
type: int
|
||||||
returned: success
|
returned: success
|
||||||
modify__count:
|
modify__count:
|
||||||
description:
|
description:
|
||||||
- The number of entries that were modified.
|
- The number of entries that were modified.
|
||||||
sample: 1
|
sample: 1
|
||||||
type: int
|
type: int
|
||||||
returned: success
|
returned: success
|
||||||
'''
|
"""
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
@ -185,6 +209,17 @@ def compose_api_path(api, path):
|
||||||
return 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', )
|
DISABLED_MEANS_EMPTY_STRING = ('comment', )
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,6 +231,8 @@ def main():
|
||||||
require_matches_min=dict(type='int', default=0),
|
require_matches_min=dict(type='int', default=0),
|
||||||
require_matches_max=dict(type='int'),
|
require_matches_max=dict(type='int'),
|
||||||
allow_no_matches=dict(type='bool'),
|
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())
|
module_args.update(api_argument_spec())
|
||||||
|
|
||||||
|
@ -223,6 +260,9 @@ def main():
|
||||||
if key in values:
|
if key in values:
|
||||||
module.fail_json(msg='`values` must not contain both "{key}" and "!{key}"!'.format(key=key))
|
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)
|
check_has_library(module)
|
||||||
api = create_api(module)
|
api = create_api(module)
|
||||||
|
|
||||||
|
@ -230,7 +270,7 @@ def main():
|
||||||
|
|
||||||
api_path = compose_api_path(api, path)
|
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]
|
new_data = [entry.copy() for entry in old_data]
|
||||||
|
|
||||||
# Find matching entries
|
# Find matching entries
|
||||||
|
@ -299,7 +339,7 @@ def main():
|
||||||
error=to_native(e),
|
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
|
# Produce return value
|
||||||
more = {}
|
more = {}
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: api_info
|
module: api_info
|
||||||
author:
|
author:
|
||||||
- "Felix Fontein (@felixfontein)"
|
- "Felix Fontein (@felixfontein)"
|
||||||
|
@ -18,17 +17,18 @@ version_added: 2.2.0
|
||||||
description:
|
description:
|
||||||
- Allows to retrieve information for a path using the API.
|
- 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.
|
- 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
|
- Entries are normalized, dynamic and builtin entries are not returned. Use the O(handle_disabled) and O(hide_defaults)
|
||||||
O(hide_defaults) options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return
|
options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return dynamic resp. builtin
|
||||||
dynamic resp. builtin entries, and use O(unfiltered) to return all fields including counters.
|
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.
|
- B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new
|
||||||
If you want to support new paths, or think you found problems with existing paths, please first
|
paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue
|
||||||
L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/).
|
Tracker,https://github.com/ansible-collections/community.routeros/issues/).
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.routeros.api
|
- community.routeros.api
|
||||||
- community.routeros.api.restrict
|
- community.routeros.api.restrict
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
- community.routeros.attributes.actiongroup_api
|
- community.routeros.attributes.actiongroup_api
|
||||||
|
- community.routeros.attributes.idempotent_not_modify_state
|
||||||
- community.routeros.attributes.info_module
|
- community.routeros.attributes.info_module
|
||||||
attributes:
|
attributes:
|
||||||
platform:
|
platform:
|
||||||
|
@ -43,224 +43,232 @@ options:
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
# BEGIN PATH LIST
|
# BEGIN PATH LIST
|
||||||
- caps-man aaa
|
- caps-man aaa
|
||||||
- caps-man access-list
|
- caps-man access-list
|
||||||
- caps-man channel
|
- caps-man channel
|
||||||
- caps-man configuration
|
- caps-man configuration
|
||||||
- caps-man datapath
|
- caps-man datapath
|
||||||
- caps-man manager
|
- caps-man manager
|
||||||
- caps-man manager interface
|
- caps-man manager interface
|
||||||
- caps-man provisioning
|
- caps-man provisioning
|
||||||
- caps-man security
|
- caps-man security
|
||||||
- certificate settings
|
- certificate settings
|
||||||
- interface bonding
|
- interface 6to4
|
||||||
- interface bridge
|
- interface bonding
|
||||||
- interface bridge mlag
|
- interface bridge
|
||||||
- interface bridge port
|
- interface bridge mlag
|
||||||
- interface bridge port-controller
|
- interface bridge port
|
||||||
- interface bridge port-extender
|
- interface bridge port-controller
|
||||||
- interface bridge settings
|
- interface bridge port-extender
|
||||||
- interface bridge vlan
|
- interface bridge settings
|
||||||
- interface detect-internet
|
- interface bridge vlan
|
||||||
- interface eoip
|
- interface detect-internet
|
||||||
- interface ethernet
|
- interface eoip
|
||||||
- interface ethernet poe
|
- interface ethernet
|
||||||
- interface ethernet switch
|
- interface ethernet poe
|
||||||
- interface ethernet switch port
|
- interface ethernet switch
|
||||||
- interface gre
|
- interface ethernet switch port
|
||||||
- interface gre6
|
- interface ethernet switch port-isolation
|
||||||
- interface l2tp-client
|
- interface gre
|
||||||
- interface l2tp-server server
|
- interface gre6
|
||||||
- interface list
|
- interface l2tp-client
|
||||||
- interface list member
|
- interface l2tp-server server
|
||||||
- interface ovpn-client
|
- interface list
|
||||||
- interface ovpn-server server
|
- interface list member
|
||||||
- interface ppp-client
|
- interface ovpn-client
|
||||||
- interface pppoe-client
|
- interface ovpn-server server
|
||||||
- interface pppoe-server server
|
- interface ppp-client
|
||||||
- interface pptp-server server
|
- interface pppoe-client
|
||||||
- interface sstp-server server
|
- interface pppoe-server server
|
||||||
- interface vlan
|
- interface pptp-server server
|
||||||
- interface vrrp
|
- interface sstp-server server
|
||||||
- interface wifi
|
- interface vlan
|
||||||
- interface wifi aaa
|
- interface vrrp
|
||||||
- interface wifi access-list
|
- interface wifi
|
||||||
- interface wifi cap
|
- interface wifi aaa
|
||||||
- interface wifi capsman
|
- interface wifi access-list
|
||||||
- interface wifi channel
|
- interface wifi cap
|
||||||
- interface wifi configuration
|
- interface wifi capsman
|
||||||
- interface wifi datapath
|
- interface wifi channel
|
||||||
- interface wifi interworking
|
- interface wifi configuration
|
||||||
- interface wifi provisioning
|
- interface wifi datapath
|
||||||
- interface wifi security
|
- interface wifi interworking
|
||||||
- interface wifi steering
|
- interface wifi provisioning
|
||||||
- interface wifiwave2
|
- interface wifi security
|
||||||
- interface wifiwave2 aaa
|
- interface wifi steering
|
||||||
- interface wifiwave2 access-list
|
- interface wifiwave2
|
||||||
- interface wifiwave2 cap
|
- interface wifiwave2 aaa
|
||||||
- interface wifiwave2 capsman
|
- interface wifiwave2 access-list
|
||||||
- interface wifiwave2 channel
|
- interface wifiwave2 cap
|
||||||
- interface wifiwave2 configuration
|
- interface wifiwave2 capsman
|
||||||
- interface wifiwave2 datapath
|
- interface wifiwave2 channel
|
||||||
- interface wifiwave2 interworking
|
- interface wifiwave2 configuration
|
||||||
- interface wifiwave2 provisioning
|
- interface wifiwave2 datapath
|
||||||
- interface wifiwave2 security
|
- interface wifiwave2 interworking
|
||||||
- interface wifiwave2 steering
|
- interface wifiwave2 provisioning
|
||||||
- interface wireguard
|
- interface wifiwave2 security
|
||||||
- interface wireguard peers
|
- interface wifiwave2 steering
|
||||||
- interface wireless
|
- interface wireguard
|
||||||
- interface wireless align
|
- interface wireguard peers
|
||||||
- interface wireless cap
|
- interface wireless
|
||||||
- interface wireless security-profiles
|
- interface wireless access-list
|
||||||
- interface wireless sniffer
|
- interface wireless align
|
||||||
- interface wireless snooper
|
- interface wireless cap
|
||||||
- iot modbus
|
- interface wireless connect-list
|
||||||
- ip accounting
|
- interface wireless security-profiles
|
||||||
- ip accounting web-access
|
- interface wireless sniffer
|
||||||
- ip address
|
- interface wireless snooper
|
||||||
- ip arp
|
- iot modbus
|
||||||
- ip cloud
|
- ip accounting
|
||||||
- ip cloud advanced
|
- ip accounting web-access
|
||||||
- ip dhcp-client
|
- ip address
|
||||||
- ip dhcp-client option
|
- ip arp
|
||||||
- ip dhcp-relay
|
- ip cloud
|
||||||
- ip dhcp-server
|
- ip cloud advanced
|
||||||
- ip dhcp-server config
|
- ip dhcp-client
|
||||||
- ip dhcp-server lease
|
- ip dhcp-client option
|
||||||
- ip dhcp-server matcher
|
- ip dhcp-relay
|
||||||
- ip dhcp-server network
|
- ip dhcp-server
|
||||||
- ip dhcp-server option
|
- ip dhcp-server config
|
||||||
- ip dhcp-server option sets
|
- ip dhcp-server lease
|
||||||
- ip dns
|
- ip dhcp-server matcher
|
||||||
- ip dns adlist
|
- ip dhcp-server network
|
||||||
- ip dns static
|
- ip dhcp-server option
|
||||||
- ip firewall address-list
|
- ip dhcp-server option sets
|
||||||
- ip firewall connection tracking
|
- ip dns
|
||||||
- ip firewall filter
|
- ip dns adlist
|
||||||
- ip firewall layer7-protocol
|
- ip dns forwarders
|
||||||
- ip firewall mangle
|
- ip dns static
|
||||||
- ip firewall nat
|
- ip firewall address-list
|
||||||
- ip firewall raw
|
- ip firewall connection tracking
|
||||||
- ip firewall service-port
|
- ip firewall filter
|
||||||
- ip hotspot service-port
|
- ip firewall layer7-protocol
|
||||||
- ip ipsec identity
|
- ip firewall mangle
|
||||||
- ip ipsec peer
|
- ip firewall nat
|
||||||
- ip ipsec policy
|
- ip firewall raw
|
||||||
- ip ipsec profile
|
- ip firewall service-port
|
||||||
- ip ipsec proposal
|
- ip hotspot service-port
|
||||||
- ip ipsec settings
|
- ip ipsec identity
|
||||||
- ip neighbor discovery-settings
|
- ip ipsec mode-config
|
||||||
- ip pool
|
- ip ipsec peer
|
||||||
- ip proxy
|
- ip ipsec policy
|
||||||
- ip route
|
- ip ipsec profile
|
||||||
- ip route rule
|
- ip ipsec proposal
|
||||||
- ip route vrf
|
- ip ipsec settings
|
||||||
- ip service
|
- ip neighbor discovery-settings
|
||||||
- ip settings
|
- ip pool
|
||||||
- ip smb
|
- ip proxy
|
||||||
- ip socks
|
- ip route
|
||||||
- ip ssh
|
- ip route rule
|
||||||
- ip tftp settings
|
- ip route vrf
|
||||||
- ip traffic-flow
|
- ip service
|
||||||
- ip traffic-flow ipfix
|
- ip settings
|
||||||
- ip traffic-flow target
|
- ip smb
|
||||||
- ip upnp
|
- ip socks
|
||||||
- ip upnp interfaces
|
- ip ssh
|
||||||
- ip vrf
|
- ip tftp settings
|
||||||
- ipv6 address
|
- ip traffic-flow
|
||||||
- ipv6 dhcp-client
|
- ip traffic-flow ipfix
|
||||||
- ipv6 dhcp-server
|
- ip traffic-flow target
|
||||||
- ipv6 dhcp-server option
|
- ip upnp
|
||||||
- ipv6 firewall address-list
|
- ip upnp interfaces
|
||||||
- ipv6 firewall filter
|
- ip vrf
|
||||||
- ipv6 firewall mangle
|
- ipv6 address
|
||||||
- ipv6 firewall nat
|
- ipv6 dhcp-client
|
||||||
- ipv6 firewall raw
|
- ipv6 dhcp-server
|
||||||
- ipv6 nd
|
- ipv6 dhcp-server option
|
||||||
- ipv6 nd prefix
|
- ipv6 firewall address-list
|
||||||
- ipv6 nd prefix default
|
- ipv6 firewall filter
|
||||||
- ipv6 route
|
- ipv6 firewall mangle
|
||||||
- ipv6 settings
|
- ipv6 firewall nat
|
||||||
- mpls
|
- ipv6 firewall raw
|
||||||
- mpls interface
|
- ipv6 nd
|
||||||
- mpls ldp
|
- ipv6 nd prefix
|
||||||
- mpls ldp accept-filter
|
- ipv6 nd prefix default
|
||||||
- mpls ldp advertise-filter
|
- ipv6 route
|
||||||
- mpls ldp interface
|
- ipv6 settings
|
||||||
- port firmware
|
- mpls
|
||||||
- port remote-access
|
- mpls interface
|
||||||
- ppp aaa
|
- mpls ldp
|
||||||
- ppp profile
|
- mpls ldp accept-filter
|
||||||
- ppp secret
|
- mpls ldp advertise-filter
|
||||||
- queue interface
|
- mpls ldp interface
|
||||||
- queue simple
|
- port firmware
|
||||||
- queue tree
|
- port remote-access
|
||||||
- queue type
|
- ppp aaa
|
||||||
- radius
|
- ppp profile
|
||||||
- radius incoming
|
- ppp secret
|
||||||
- routing bgp aggregate
|
- queue interface
|
||||||
- routing bgp connection
|
- queue simple
|
||||||
- routing bgp instance
|
- queue tree
|
||||||
- routing bgp network
|
- queue type
|
||||||
- routing bgp peer
|
- radius
|
||||||
- routing bgp template
|
- radius incoming
|
||||||
- routing filter
|
- routing bfd configuration
|
||||||
- routing filter num-list
|
- routing bgp aggregate
|
||||||
- routing filter rule
|
- routing bgp connection
|
||||||
- routing filter select-rule
|
- routing bgp instance
|
||||||
- routing id
|
- routing bgp network
|
||||||
- routing igmp-proxy
|
- routing bgp peer
|
||||||
- routing igmp-proxy interface
|
- routing bgp template
|
||||||
- routing mme
|
- routing filter
|
||||||
- routing ospf area
|
- routing filter community-list
|
||||||
- routing ospf area range
|
- routing filter num-list
|
||||||
- routing ospf instance
|
- routing filter rule
|
||||||
- routing ospf interface-template
|
- routing filter select-rule
|
||||||
- routing ospf static-neighbor
|
- routing id
|
||||||
- routing pimsm instance
|
- routing igmp-proxy
|
||||||
- routing pimsm interface-template
|
- routing igmp-proxy interface
|
||||||
- routing rip
|
- routing mme
|
||||||
- routing ripng
|
- routing ospf area
|
||||||
- routing rule
|
- routing ospf area range
|
||||||
- routing table
|
- routing ospf instance
|
||||||
- snmp
|
- routing ospf interface-template
|
||||||
- snmp community
|
- routing ospf static-neighbor
|
||||||
- system clock
|
- routing pimsm instance
|
||||||
- system clock manual
|
- routing pimsm interface-template
|
||||||
- system health settings
|
- routing rip
|
||||||
- system identity
|
- routing ripng
|
||||||
- system leds settings
|
- routing rule
|
||||||
- system logging
|
- routing table
|
||||||
- system logging action
|
- snmp
|
||||||
- system note
|
- snmp community
|
||||||
- system ntp client
|
- system clock
|
||||||
- system ntp client servers
|
- system clock manual
|
||||||
- system ntp server
|
- system health settings
|
||||||
- system package update
|
- system identity
|
||||||
- system resource irq rps
|
- system leds settings
|
||||||
- system routerboard settings
|
- system logging
|
||||||
- system scheduler
|
- system logging action
|
||||||
- system script
|
- system note
|
||||||
- system upgrade mirror
|
- system ntp client
|
||||||
- system ups
|
- system ntp client servers
|
||||||
- system watchdog
|
- system ntp server
|
||||||
- tool bandwidth-server
|
- system package update
|
||||||
- tool e-mail
|
- system resource irq rps
|
||||||
- tool graphing
|
- system routerboard settings
|
||||||
- tool graphing interface
|
- system scheduler
|
||||||
- tool graphing resource
|
- system script
|
||||||
- tool mac-server
|
- system upgrade mirror
|
||||||
- tool mac-server mac-winbox
|
- system ups
|
||||||
- tool mac-server ping
|
- system watchdog
|
||||||
- tool netwatch
|
- tool bandwidth-server
|
||||||
- tool romon
|
- tool e-mail
|
||||||
- tool sms
|
- tool graphing
|
||||||
- tool sniffer
|
- tool graphing interface
|
||||||
- tool traffic-generator
|
- tool graphing resource
|
||||||
- user
|
- tool mac-server
|
||||||
- user aaa
|
- tool mac-server mac-winbox
|
||||||
- user group
|
- tool mac-server ping
|
||||||
- user settings
|
- tool netwatch
|
||||||
|
- tool romon
|
||||||
|
- tool sms
|
||||||
|
- tool sniffer
|
||||||
|
- tool traffic-generator
|
||||||
|
- user
|
||||||
|
- user aaa
|
||||||
|
- user group
|
||||||
|
- user settings
|
||||||
# END PATH LIST
|
# END PATH LIST
|
||||||
unfiltered:
|
unfiltered:
|
||||||
description:
|
description:
|
||||||
|
@ -316,9 +324,9 @@ seealso:
|
||||||
- module: community.routeros.api_facts
|
- module: community.routeros.api_facts
|
||||||
- module: community.routeros.api_find_and_modify
|
- module: community.routeros.api_find_and_modify
|
||||||
- module: community.routeros.api_modify
|
- module: community.routeros.api_modify
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = r"""
|
||||||
---
|
---
|
||||||
- name: Get IP addresses
|
- name: Get IP addresses
|
||||||
community.routeros.api_info:
|
community.routeros.api_info:
|
||||||
|
@ -343,26 +351,25 @@ EXAMPLES = '''
|
||||||
- name: Print data for IP addresses
|
- name: Print data for IP addresses
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
var: ip_addresses.result
|
var: ip_addresses.result
|
||||||
'''
|
"""
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = r"""
|
||||||
---
|
|
||||||
result:
|
result:
|
||||||
description: A list of all elements for the current path.
|
description: A list of all elements for the current path.
|
||||||
sample:
|
sample:
|
||||||
- '.id': '*1'
|
- '.id': '*1'
|
||||||
actual-interface: bridge
|
actual-interface: bridge
|
||||||
address: "192.168.88.1/24"
|
address: "192.168.88.1/24"
|
||||||
comment: defconf
|
comment: defconf
|
||||||
disabled: false
|
disabled: false
|
||||||
dynamic: false
|
dynamic: false
|
||||||
interface: bridge
|
interface: bridge
|
||||||
invalid: false
|
invalid: false
|
||||||
network: 192.168.88.0
|
network: 192.168.88.0
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
returned: always
|
returned: always
|
||||||
'''
|
"""
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: api_modify
|
module: api_modify
|
||||||
author:
|
author:
|
||||||
- "Felix Fontein (@felixfontein)"
|
- "Felix Fontein (@felixfontein)"
|
||||||
|
@ -17,17 +16,17 @@ short_description: Modify data at paths with API
|
||||||
version_added: 2.2.0
|
version_added: 2.2.0
|
||||||
description:
|
description:
|
||||||
- Allows to modify information for a path using the API.
|
- 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
|
- Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way depending
|
||||||
depending on some search conditions.
|
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.
|
- 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.
|
- The module ignores dynamic and builtin entries.
|
||||||
- B(Note) that this module is still heavily in development, and only supports B(some) paths.
|
- B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new
|
||||||
If you want to support new paths, or think you found problems with existing paths, please first
|
paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue
|
||||||
L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/).
|
Tracker,https://github.com/ansible-collections/community.routeros/issues/).
|
||||||
notes:
|
notes:
|
||||||
- If write-only fields are present in the path, the module is B(not idempotent) in a strict sense,
|
- If write-only fields are present in the path, the module is B(not idempotent) in a strict sense, since it is not able
|
||||||
since it is not able to verify the current value of these fields. The behavior the module should
|
to verify the current value of these fields. The behavior the module should assume can be controlled with the O(handle_write_only)
|
||||||
assume can be controlled with the O(handle_write_only) option.
|
option.
|
||||||
requirements:
|
requirements:
|
||||||
- Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6
|
- Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
|
@ -43,233 +42,244 @@ attributes:
|
||||||
platform:
|
platform:
|
||||||
support: full
|
support: full
|
||||||
platforms: RouterOS
|
platforms: RouterOS
|
||||||
|
idempotent:
|
||||||
|
support: full
|
||||||
options:
|
options:
|
||||||
path:
|
path:
|
||||||
description:
|
description:
|
||||||
- Path to query.
|
- 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
|
required: true
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
# BEGIN PATH LIST
|
# BEGIN PATH LIST
|
||||||
- caps-man aaa
|
- caps-man aaa
|
||||||
- caps-man access-list
|
- caps-man access-list
|
||||||
- caps-man channel
|
- caps-man channel
|
||||||
- caps-man configuration
|
- caps-man configuration
|
||||||
- caps-man datapath
|
- caps-man datapath
|
||||||
- caps-man manager
|
- caps-man manager
|
||||||
- caps-man manager interface
|
- caps-man manager interface
|
||||||
- caps-man provisioning
|
- caps-man provisioning
|
||||||
- caps-man security
|
- caps-man security
|
||||||
- certificate settings
|
- certificate settings
|
||||||
- interface bonding
|
- interface 6to4
|
||||||
- interface bridge
|
- interface bonding
|
||||||
- interface bridge mlag
|
- interface bridge
|
||||||
- interface bridge port
|
- interface bridge mlag
|
||||||
- interface bridge port-controller
|
- interface bridge port
|
||||||
- interface bridge port-extender
|
- interface bridge port-controller
|
||||||
- interface bridge settings
|
- interface bridge port-extender
|
||||||
- interface bridge vlan
|
- interface bridge settings
|
||||||
- interface detect-internet
|
- interface bridge vlan
|
||||||
- interface eoip
|
- interface detect-internet
|
||||||
- interface ethernet
|
- interface eoip
|
||||||
- interface ethernet poe
|
- interface ethernet
|
||||||
- interface ethernet switch
|
- interface ethernet poe
|
||||||
- interface ethernet switch port
|
- interface ethernet switch
|
||||||
- interface gre
|
- interface ethernet switch port
|
||||||
- interface gre6
|
- interface ethernet switch port-isolation
|
||||||
- interface l2tp-client
|
- interface gre
|
||||||
- interface l2tp-server server
|
- interface gre6
|
||||||
- interface list
|
- interface l2tp-client
|
||||||
- interface list member
|
- interface l2tp-server server
|
||||||
- interface ovpn-client
|
- interface list
|
||||||
- interface ovpn-server server
|
- interface list member
|
||||||
- interface ppp-client
|
- interface ovpn-client
|
||||||
- interface pppoe-client
|
- interface ovpn-server server
|
||||||
- interface pppoe-server server
|
- interface ppp-client
|
||||||
- interface pptp-server server
|
- interface pppoe-client
|
||||||
- interface sstp-server server
|
- interface pppoe-server server
|
||||||
- interface vlan
|
- interface pptp-server server
|
||||||
- interface vrrp
|
- interface sstp-server server
|
||||||
- interface wifi
|
- interface vlan
|
||||||
- interface wifi aaa
|
- interface vrrp
|
||||||
- interface wifi access-list
|
- interface wifi
|
||||||
- interface wifi cap
|
- interface wifi aaa
|
||||||
- interface wifi capsman
|
- interface wifi access-list
|
||||||
- interface wifi channel
|
- interface wifi cap
|
||||||
- interface wifi configuration
|
- interface wifi capsman
|
||||||
- interface wifi datapath
|
- interface wifi channel
|
||||||
- interface wifi interworking
|
- interface wifi configuration
|
||||||
- interface wifi provisioning
|
- interface wifi datapath
|
||||||
- interface wifi security
|
- interface wifi interworking
|
||||||
- interface wifi steering
|
- interface wifi provisioning
|
||||||
- interface wifiwave2
|
- interface wifi security
|
||||||
- interface wifiwave2 aaa
|
- interface wifi steering
|
||||||
- interface wifiwave2 access-list
|
- interface wifiwave2
|
||||||
- interface wifiwave2 cap
|
- interface wifiwave2 aaa
|
||||||
- interface wifiwave2 capsman
|
- interface wifiwave2 access-list
|
||||||
- interface wifiwave2 channel
|
- interface wifiwave2 cap
|
||||||
- interface wifiwave2 configuration
|
- interface wifiwave2 capsman
|
||||||
- interface wifiwave2 datapath
|
- interface wifiwave2 channel
|
||||||
- interface wifiwave2 interworking
|
- interface wifiwave2 configuration
|
||||||
- interface wifiwave2 provisioning
|
- interface wifiwave2 datapath
|
||||||
- interface wifiwave2 security
|
- interface wifiwave2 interworking
|
||||||
- interface wifiwave2 steering
|
- interface wifiwave2 provisioning
|
||||||
- interface wireguard
|
- interface wifiwave2 security
|
||||||
- interface wireguard peers
|
- interface wifiwave2 steering
|
||||||
- interface wireless
|
- interface wireguard
|
||||||
- interface wireless align
|
- interface wireguard peers
|
||||||
- interface wireless cap
|
- interface wireless
|
||||||
- interface wireless security-profiles
|
- interface wireless access-list
|
||||||
- interface wireless sniffer
|
- interface wireless align
|
||||||
- interface wireless snooper
|
- interface wireless cap
|
||||||
- iot modbus
|
- interface wireless connect-list
|
||||||
- ip accounting
|
- interface wireless security-profiles
|
||||||
- ip accounting web-access
|
- interface wireless sniffer
|
||||||
- ip address
|
- interface wireless snooper
|
||||||
- ip arp
|
- iot modbus
|
||||||
- ip cloud
|
- ip accounting
|
||||||
- ip cloud advanced
|
- ip accounting web-access
|
||||||
- ip dhcp-client
|
- ip address
|
||||||
- ip dhcp-client option
|
- ip arp
|
||||||
- ip dhcp-relay
|
- ip cloud
|
||||||
- ip dhcp-server
|
- ip cloud advanced
|
||||||
- ip dhcp-server config
|
- ip dhcp-client
|
||||||
- ip dhcp-server lease
|
- ip dhcp-client option
|
||||||
- ip dhcp-server matcher
|
- ip dhcp-relay
|
||||||
- ip dhcp-server network
|
- ip dhcp-server
|
||||||
- ip dhcp-server option
|
- ip dhcp-server config
|
||||||
- ip dhcp-server option sets
|
- ip dhcp-server lease
|
||||||
- ip dns
|
- ip dhcp-server matcher
|
||||||
- ip dns adlist
|
- ip dhcp-server network
|
||||||
- ip dns static
|
- ip dhcp-server option
|
||||||
- ip firewall address-list
|
- ip dhcp-server option sets
|
||||||
- ip firewall connection tracking
|
- ip dns
|
||||||
- ip firewall filter
|
- ip dns adlist
|
||||||
- ip firewall layer7-protocol
|
- ip dns forwarders
|
||||||
- ip firewall mangle
|
- ip dns static
|
||||||
- ip firewall nat
|
- ip firewall address-list
|
||||||
- ip firewall raw
|
- ip firewall connection tracking
|
||||||
- ip firewall service-port
|
- ip firewall filter
|
||||||
- ip hotspot service-port
|
- ip firewall layer7-protocol
|
||||||
- ip ipsec identity
|
- ip firewall mangle
|
||||||
- ip ipsec peer
|
- ip firewall nat
|
||||||
- ip ipsec policy
|
- ip firewall raw
|
||||||
- ip ipsec profile
|
- ip firewall service-port
|
||||||
- ip ipsec proposal
|
- ip hotspot service-port
|
||||||
- ip ipsec settings
|
- ip ipsec identity
|
||||||
- ip neighbor discovery-settings
|
- ip ipsec mode-config
|
||||||
- ip pool
|
- ip ipsec peer
|
||||||
- ip proxy
|
- ip ipsec policy
|
||||||
- ip route
|
- ip ipsec profile
|
||||||
- ip route rule
|
- ip ipsec proposal
|
||||||
- ip route vrf
|
- ip ipsec settings
|
||||||
- ip service
|
- ip neighbor discovery-settings
|
||||||
- ip settings
|
- ip pool
|
||||||
- ip smb
|
- ip proxy
|
||||||
- ip socks
|
- ip route
|
||||||
- ip ssh
|
- ip route rule
|
||||||
- ip tftp settings
|
- ip route vrf
|
||||||
- ip traffic-flow
|
- ip service
|
||||||
- ip traffic-flow ipfix
|
- ip settings
|
||||||
- ip traffic-flow target
|
- ip smb
|
||||||
- ip upnp
|
- ip socks
|
||||||
- ip upnp interfaces
|
- ip ssh
|
||||||
- ip vrf
|
- ip tftp settings
|
||||||
- ipv6 address
|
- ip traffic-flow
|
||||||
- ipv6 dhcp-client
|
- ip traffic-flow ipfix
|
||||||
- ipv6 dhcp-server
|
- ip traffic-flow target
|
||||||
- ipv6 dhcp-server option
|
- ip upnp
|
||||||
- ipv6 firewall address-list
|
- ip upnp interfaces
|
||||||
- ipv6 firewall filter
|
- ip vrf
|
||||||
- ipv6 firewall mangle
|
- ipv6 address
|
||||||
- ipv6 firewall nat
|
- ipv6 dhcp-client
|
||||||
- ipv6 firewall raw
|
- ipv6 dhcp-server
|
||||||
- ipv6 nd
|
- ipv6 dhcp-server option
|
||||||
- ipv6 nd prefix
|
- ipv6 firewall address-list
|
||||||
- ipv6 nd prefix default
|
- ipv6 firewall filter
|
||||||
- ipv6 route
|
- ipv6 firewall mangle
|
||||||
- ipv6 settings
|
- ipv6 firewall nat
|
||||||
- mpls
|
- ipv6 firewall raw
|
||||||
- mpls interface
|
- ipv6 nd
|
||||||
- mpls ldp
|
- ipv6 nd prefix
|
||||||
- mpls ldp accept-filter
|
- ipv6 nd prefix default
|
||||||
- mpls ldp advertise-filter
|
- ipv6 route
|
||||||
- mpls ldp interface
|
- ipv6 settings
|
||||||
- port firmware
|
- mpls
|
||||||
- port remote-access
|
- mpls interface
|
||||||
- ppp aaa
|
- mpls ldp
|
||||||
- ppp profile
|
- mpls ldp accept-filter
|
||||||
- ppp secret
|
- mpls ldp advertise-filter
|
||||||
- queue interface
|
- mpls ldp interface
|
||||||
- queue simple
|
- port firmware
|
||||||
- queue tree
|
- port remote-access
|
||||||
- queue type
|
- ppp aaa
|
||||||
- radius
|
- ppp profile
|
||||||
- radius incoming
|
- ppp secret
|
||||||
- routing bgp aggregate
|
- queue interface
|
||||||
- routing bgp connection
|
- queue simple
|
||||||
- routing bgp instance
|
- queue tree
|
||||||
- routing bgp network
|
- queue type
|
||||||
- routing bgp peer
|
- radius
|
||||||
- routing bgp template
|
- radius incoming
|
||||||
- routing filter
|
- routing bfd configuration
|
||||||
- routing filter num-list
|
- routing bgp aggregate
|
||||||
- routing filter rule
|
- routing bgp connection
|
||||||
- routing filter select-rule
|
- routing bgp instance
|
||||||
- routing id
|
- routing bgp network
|
||||||
- routing igmp-proxy
|
- routing bgp peer
|
||||||
- routing igmp-proxy interface
|
- routing bgp template
|
||||||
- routing mme
|
- routing filter
|
||||||
- routing ospf area
|
- routing filter community-list
|
||||||
- routing ospf area range
|
- routing filter num-list
|
||||||
- routing ospf instance
|
- routing filter rule
|
||||||
- routing ospf interface-template
|
- routing filter select-rule
|
||||||
- routing ospf static-neighbor
|
- routing id
|
||||||
- routing pimsm instance
|
- routing igmp-proxy
|
||||||
- routing pimsm interface-template
|
- routing igmp-proxy interface
|
||||||
- routing rip
|
- routing mme
|
||||||
- routing ripng
|
- routing ospf area
|
||||||
- routing rule
|
- routing ospf area range
|
||||||
- routing table
|
- routing ospf instance
|
||||||
- snmp
|
- routing ospf interface-template
|
||||||
- snmp community
|
- routing ospf static-neighbor
|
||||||
- system clock
|
- routing pimsm instance
|
||||||
- system clock manual
|
- routing pimsm interface-template
|
||||||
- system health settings
|
- routing rip
|
||||||
- system identity
|
- routing ripng
|
||||||
- system leds settings
|
- routing rule
|
||||||
- system logging
|
- routing table
|
||||||
- system logging action
|
- snmp
|
||||||
- system note
|
- snmp community
|
||||||
- system ntp client
|
- system clock
|
||||||
- system ntp client servers
|
- system clock manual
|
||||||
- system ntp server
|
- system health settings
|
||||||
- system package update
|
- system identity
|
||||||
- system resource irq rps
|
- system leds settings
|
||||||
- system routerboard settings
|
- system logging
|
||||||
- system scheduler
|
- system logging action
|
||||||
- system script
|
- system note
|
||||||
- system upgrade mirror
|
- system ntp client
|
||||||
- system ups
|
- system ntp client servers
|
||||||
- system watchdog
|
- system ntp server
|
||||||
- tool bandwidth-server
|
- system package update
|
||||||
- tool e-mail
|
- system resource irq rps
|
||||||
- tool graphing
|
- system routerboard settings
|
||||||
- tool graphing interface
|
- system scheduler
|
||||||
- tool graphing resource
|
- system script
|
||||||
- tool mac-server
|
- system upgrade mirror
|
||||||
- tool mac-server mac-winbox
|
- system ups
|
||||||
- tool mac-server ping
|
- system watchdog
|
||||||
- tool netwatch
|
- tool bandwidth-server
|
||||||
- tool romon
|
- tool e-mail
|
||||||
- tool sms
|
- tool graphing
|
||||||
- tool sniffer
|
- tool graphing interface
|
||||||
- tool traffic-generator
|
- tool graphing resource
|
||||||
- user
|
- tool mac-server
|
||||||
- user aaa
|
- tool mac-server mac-winbox
|
||||||
- user group
|
- tool mac-server ping
|
||||||
- user settings
|
- tool netwatch
|
||||||
|
- tool romon
|
||||||
|
- tool sms
|
||||||
|
- tool sniffer
|
||||||
|
- tool traffic-generator
|
||||||
|
- user
|
||||||
|
- user aaa
|
||||||
|
- user group
|
||||||
|
- user settings
|
||||||
# END PATH LIST
|
# END PATH LIST
|
||||||
data:
|
data:
|
||||||
description:
|
description:
|
||||||
|
@ -297,12 +307,12 @@ options:
|
||||||
default: ignore
|
default: ignore
|
||||||
handle_entries_content:
|
handle_entries_content:
|
||||||
description:
|
description:
|
||||||
- For a single entry in O(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 that entry, but appear in the actual config.
|
in the actual config.
|
||||||
- If V(ignore), they are not modified.
|
- 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), 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
|
- If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that cannot be removed will be
|
||||||
cannot be removed will be kept.
|
kept.
|
||||||
- Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields.
|
- Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields.
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
|
@ -314,8 +324,8 @@ options:
|
||||||
description:
|
description:
|
||||||
- How to handle values passed in for read-only fields.
|
- How to handle values passed in for read-only fields.
|
||||||
- If V(ignore), they are not passed to the API.
|
- 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 V(validate), the values are not passed for creation, and for updating they are compared to the value returned for
|
||||||
If they differ, the module fails.
|
the object. If they differ, the module fails.
|
||||||
- If V(error), the module will fail if read-only fields are provided.
|
- If V(error), the module will fail if read-only fields are provided.
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
|
@ -328,9 +338,8 @@ options:
|
||||||
description:
|
description:
|
||||||
- How to handle values passed in for write-only fields.
|
- 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(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,
|
- If V(always_update), they are always passed to the API. This means that if such a value is present, the module will
|
||||||
the module will always result in C(changed) since there is no way to validate whether the value
|
always result in C(changed) since there is no way to validate whether the value actually changed.
|
||||||
actually changed.
|
|
||||||
- If V(error), the module will fail if write-only fields are provided.
|
- If V(error), the module will fail if write-only fields are provided.
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
|
@ -342,20 +351,18 @@ options:
|
||||||
restrict:
|
restrict:
|
||||||
description:
|
description:
|
||||||
- Restrict operation to entries matching the following criteria.
|
- 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
|
- This can be useful together with O(handle_absent_entries=remove) to operate on a subset of the values.
|
||||||
the values.
|
- For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and O(restrict[].values=input)
|
||||||
- For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and
|
to restrict operation to the input chain, and ignore the forward and output chains.
|
||||||
O(restrict[].values=input) to restrict operation to the input chain, and ignore the
|
|
||||||
forward and output chains.
|
|
||||||
version_added: 2.18.0
|
version_added: 2.18.0
|
||||||
seealso:
|
seealso:
|
||||||
- module: community.routeros.api
|
- module: community.routeros.api
|
||||||
- module: community.routeros.api_facts
|
- module: community.routeros.api_facts
|
||||||
- module: community.routeros.api_find_and_modify
|
- module: community.routeros.api_find_and_modify
|
||||||
- module: community.routeros.api_info
|
- module: community.routeros.api_info
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = r"""
|
||||||
---
|
---
|
||||||
- name: Setup DHCP server networks
|
- name: Setup DHCP server networks
|
||||||
# Ensures that we have exactly two DHCP server networks (in the specified order)
|
# Ensures that we have exactly two DHCP server networks (in the specified order)
|
||||||
|
@ -410,43 +417,42 @@ EXAMPLES = '''
|
||||||
data:
|
data:
|
||||||
- action: drop
|
- action: drop
|
||||||
chain: input
|
chain: input
|
||||||
'''
|
"""
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = r"""
|
||||||
---
|
|
||||||
old_data:
|
old_data:
|
||||||
description:
|
description:
|
||||||
- A list of all elements for the current path before a change was made.
|
- A list of all elements for the current path before a change was made.
|
||||||
sample:
|
sample:
|
||||||
- '.id': '*1'
|
- '.id': '*1'
|
||||||
actual-interface: bridge
|
actual-interface: bridge
|
||||||
address: "192.168.88.1/24"
|
address: "192.168.88.1/24"
|
||||||
comment: defconf
|
comment: defconf
|
||||||
disabled: false
|
disabled: false
|
||||||
dynamic: false
|
dynamic: false
|
||||||
interface: bridge
|
interface: bridge
|
||||||
invalid: false
|
invalid: false
|
||||||
network: 192.168.88.0
|
network: 192.168.88.0
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
returned: always
|
returned: always
|
||||||
new_data:
|
new_data:
|
||||||
description:
|
description:
|
||||||
- A list of all elements for the current path after a change was made.
|
- A list of all elements for the current path after a change was made.
|
||||||
sample:
|
sample:
|
||||||
- '.id': '*1'
|
- '.id': '*1'
|
||||||
actual-interface: bridge
|
actual-interface: bridge
|
||||||
address: "192.168.1.1/24"
|
address: "192.168.1.1/24"
|
||||||
comment: awesome
|
comment: awesome
|
||||||
disabled: false
|
disabled: false
|
||||||
dynamic: false
|
dynamic: false
|
||||||
interface: bridge
|
interface: bridge
|
||||||
invalid: false
|
invalid: false
|
||||||
network: 192.168.1.0
|
network: 192.168.1.0
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
returned: always
|
returned: always
|
||||||
'''
|
"""
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
|
@ -7,89 +7,77 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: command
|
module: command
|
||||||
author: "Egor Zaitsev (@heuels)"
|
author: "Egor Zaitsev (@heuels)"
|
||||||
short_description: Run commands on remote devices running MikroTik RouterOS
|
short_description: Run commands on remote devices running MikroTik RouterOS
|
||||||
description:
|
description:
|
||||||
- Sends arbitrary commands to an RouterOS node and returns the results
|
- Sends arbitrary commands to an RouterOS node and returns the results read from the device. This module includes an argument
|
||||||
read from the device. This module includes an
|
that will cause the module to wait for a specific condition before returning or timing out if the condition is not met.
|
||||||
argument that will cause the module to wait for a specific condition
|
- The module always indicates a (changed) status. You can use R(the changed_when task property,override_the_changed_result)
|
||||||
before returning or timing out if the condition is not met.
|
to determine whether a command task actually resulted in a change or not.
|
||||||
- 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:
|
extends_documentation_fragment:
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
support: partial
|
support: none
|
||||||
details:
|
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:
|
diff_mode:
|
||||||
support: none
|
support: none
|
||||||
platform:
|
platform:
|
||||||
support: full
|
support: full
|
||||||
platforms: RouterOS
|
platforms: RouterOS
|
||||||
|
idempotent:
|
||||||
|
support: N/A
|
||||||
|
details:
|
||||||
|
- Whether the executed command is idempotent depends on the command.
|
||||||
options:
|
options:
|
||||||
commands:
|
commands:
|
||||||
description:
|
description:
|
||||||
- List of commands to send to the remote RouterOS device over the
|
- List of commands to send to the remote RouterOS device over the configured provider. The resulting output from the
|
||||||
configured provider. The resulting output from the command
|
command is returned. If the O(wait_for) argument is provided, the module is not returned until the condition is satisfied
|
||||||
is returned. If the O(wait_for) argument is provided, the
|
or the number of retries has expired.
|
||||||
module is not returned until the condition is satisfied or
|
|
||||||
the number of retries has expired.
|
|
||||||
required: true
|
required: true
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
wait_for:
|
wait_for:
|
||||||
description:
|
description:
|
||||||
- List of conditions to evaluate against the output of the
|
- List of conditions to evaluate against the output of the command. The task will wait for each condition to be true
|
||||||
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
|
||||||
before moving forward. If the conditional is not true
|
examples.
|
||||||
within the configured number of retries, the task fails.
|
|
||||||
See examples.
|
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
match:
|
match:
|
||||||
description:
|
description:
|
||||||
- The O(match) argument is used in conjunction with the
|
- The O(match) argument is used in conjunction with the O(wait_for) argument to specify the match policy. Valid values
|
||||||
O(wait_for) argument to specify the match policy. Valid
|
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
|
||||||
values are V(all) or V(any). If the value is set to V(all)
|
value is set to V(any) then only one of the values must be satisfied.
|
||||||
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
|
default: all
|
||||||
choices: ['any', 'all']
|
choices: ['any', 'all']
|
||||||
type: str
|
type: str
|
||||||
retries:
|
retries:
|
||||||
description:
|
description:
|
||||||
- Specifies the number of retries a command should by tried
|
- Specifies the number of retries a command should by tried before it is considered failed. The command is run on the
|
||||||
before it is considered failed. The command is run on the
|
target device every retry and evaluated against the O(wait_for) conditions.
|
||||||
target device every retry and evaluated against the
|
|
||||||
O(wait_for) conditions.
|
|
||||||
default: 10
|
default: 10
|
||||||
type: int
|
type: int
|
||||||
interval:
|
interval:
|
||||||
description:
|
description:
|
||||||
- Configures the interval in seconds to wait between retries
|
- Configures the interval in seconds to wait between retries of the command. If the command does not pass the specified
|
||||||
of the command. If the command does not pass the specified
|
conditions, the interval indicates how long to wait before trying the command again.
|
||||||
conditions, the interval indicates how long to wait before
|
|
||||||
trying the command again.
|
|
||||||
default: 1
|
default: 1
|
||||||
type: int
|
type: int
|
||||||
seealso:
|
seealso:
|
||||||
- ref: ansible_collections.community.routeros.docsite.ssh-guide
|
- 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
|
- 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
|
- name: Run command on remote devices
|
||||||
community.routeros.command:
|
community.routeros.command:
|
||||||
commands: /system routerboard print
|
commands: /system routerboard print
|
||||||
|
@ -115,19 +103,19 @@ EXAMPLES = """
|
||||||
- result[1] contains ether1
|
- result[1] contains ether1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = r"""
|
||||||
stdout:
|
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)
|
returned: always apart from low level errors (such as action plugin)
|
||||||
type: list
|
type: list
|
||||||
sample: ['...', '...']
|
sample: ['...', '...']
|
||||||
stdout_lines:
|
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)
|
returned: always apart from low level errors (such as action plugin)
|
||||||
type: list
|
type: list
|
||||||
sample: [['...', '...'], ['...'], ['...']]
|
sample: [['...', '...'], ['...'], ['...']]
|
||||||
failed_conditions:
|
failed_conditions:
|
||||||
description: The list of conditionals that have failed
|
description: The list of conditionals that have failed.
|
||||||
returned: failed
|
returned: failed
|
||||||
type: list
|
type: list
|
||||||
sample: ['...', '...']
|
sample: ['...', '...']
|
||||||
|
@ -165,7 +153,7 @@ def main():
|
||||||
argument_spec.update(routeros_argument_spec)
|
argument_spec.update(routeros_argument_spec)
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True)
|
supports_check_mode=False)
|
||||||
|
|
||||||
result = {'changed': False}
|
result = {'changed': False}
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,19 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r"""
|
||||||
---
|
|
||||||
module: facts
|
module: facts
|
||||||
author: "Egor Zaitsev (@heuels)"
|
author: "Egor Zaitsev (@heuels)"
|
||||||
short_description: Collect facts from remote devices running MikroTik RouterOS
|
short_description: Collect facts from remote devices running MikroTik RouterOS
|
||||||
description:
|
description:
|
||||||
- Collects a base set of device facts from a remote device that
|
- Collects a base set of device facts from a remote device that is running RouterOS. This module prepends all of the base
|
||||||
is running RouterOS. This module prepends all of the
|
network fact keys with C(ansible_net_<fact>). The facts module will always collect a base set of facts from the device
|
||||||
base network fact keys with C(ansible_net_<fact>). The facts
|
|
||||||
module will always collect a base set of facts from the device
|
|
||||||
and can enable or disable collection of additional facts.
|
and can enable or disable collection of additional facts.
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.routeros.attributes
|
- community.routeros.attributes
|
||||||
- community.routeros.attributes.facts
|
- community.routeros.attributes.facts
|
||||||
- community.routeros.attributes.facts_module
|
- community.routeros.attributes.facts_module
|
||||||
|
- community.routeros.attributes.idempotent_not_modify_state
|
||||||
attributes:
|
attributes:
|
||||||
platform:
|
platform:
|
||||||
support: full
|
support: full
|
||||||
|
@ -29,12 +27,10 @@ attributes:
|
||||||
options:
|
options:
|
||||||
gather_subset:
|
gather_subset:
|
||||||
description:
|
description:
|
||||||
- When supplied, this argument will restrict the facts collected
|
- When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument
|
||||||
to a given subset. Possible values for this argument include
|
include V(all), V(hardware), V(config), V(interfaces), and V(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 V(!) to specify that
|
||||||
- Can specify a list of values to include a larger subset.
|
a specific subset should not be collected.
|
||||||
Values can also be used with an initial V(!) to specify that a
|
|
||||||
specific subset should not be collected.
|
|
||||||
required: false
|
required: false
|
||||||
default:
|
default:
|
||||||
- '!config'
|
- '!config'
|
||||||
|
@ -42,10 +38,11 @@ options:
|
||||||
elements: str
|
elements: str
|
||||||
seealso:
|
seealso:
|
||||||
- ref: ansible_collections.community.routeros.docsite.ssh-guide
|
- 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
|
- name: Collect all facts from the device
|
||||||
community.routeros.facts:
|
community.routeros.facts:
|
||||||
gather_subset: all
|
gather_subset: all
|
||||||
|
@ -61,7 +58,7 @@ EXAMPLES = """
|
||||||
- "!hardware"
|
- "!hardware"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = r"""
|
||||||
ansible_facts:
|
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
|
returned: always
|
||||||
|
@ -129,9 +126,9 @@ ansible_facts:
|
||||||
ansible_net_config_nonverbose:
|
ansible_net_config_nonverbose:
|
||||||
description:
|
description:
|
||||||
- The current active config from the device in minimal form.
|
- 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
|
- This value is idempotent in the sense that if the facts module is run twice and the device's config was not changed
|
||||||
was not changed between the runs, the value is identical. This is achieved by running C(/export)
|
between the runs, the value is identical. This is achieved by running C(/export) and stripping the timestamp from
|
||||||
and stripping the timestamp from the comment in the first line.
|
the comment in the first line.
|
||||||
returned: O(gather_subset) contains V(config)
|
returned: O(gather_subset) contains V(config)
|
||||||
type: str
|
type: str
|
||||||
version_added: 1.2.0
|
version_added: 1.2.0
|
||||||
|
@ -592,8 +589,6 @@ FACT_SUBSETS = dict(
|
||||||
|
|
||||||
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
|
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
|
||||||
|
|
||||||
warnings = list()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""main entry point for module execution
|
"""main entry point for module execution
|
||||||
|
@ -656,7 +651,7 @@ def main():
|
||||||
key = 'ansible_net_%s' % key
|
key = 'ansible_net_%s' % key
|
||||||
ansible_facts[key] = value
|
ansible_facts[key] = value
|
||||||
|
|
||||||
module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
|
module.exit_json(ansible_facts=ansible_facts)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -31,7 +31,9 @@ class TerminalModule(TerminalBase):
|
||||||
|
|
||||||
terminal_stdout_re = [
|
terminal_stdout_re = [
|
||||||
re.compile(br"\x1b<"),
|
re.compile(br"\x1b<"),
|
||||||
re.compile(br"\[[\w\-\.]+\@[\w\s\-\.\/]+\] ?(<SAFE)?> ?$"),
|
re.compile(
|
||||||
|
br"((\[[\w\-\.]+\@)|(\r\<(([\w\-\.]*\@)|)))"
|
||||||
|
br"[\w\s\-\.\/]+\] ?(<SAFE)?> ?$"),
|
||||||
re.compile(br"Please press \"Enter\" to continue!"),
|
re.compile(br"Please press \"Enter\" to continue!"),
|
||||||
re.compile(br"Do you want to see the software license\? \[Y\/n\]: ?"),
|
re.compile(br"Do you want to see the software license\? \[Y\/n\]: ?"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
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"
|
- name: "Test quote_argument filter"
|
||||||
assert:
|
assert:
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
collections:
|
collections:
|
||||||
- ansible.netcommon
|
- ansible.netcommon
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
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"
|
- name: "Test quote_argument filter"
|
||||||
assert:
|
assert:
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"include_symlinks": false,
|
|
||||||
"prefixes": [
|
|
||||||
"docs/docsite/",
|
|
||||||
"plugins/",
|
|
||||||
"roles/"
|
|
||||||
],
|
|
||||||
"output": "path-line-column-message",
|
|
||||||
"requirements": [
|
|
||||||
"ansible-core",
|
|
||||||
"antsibull-docs"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -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()
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"include_symlinks": false,
|
|
||||||
"output": "path-message"
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -1,110 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Copyright (c) 2022, Felix Fontein <felix@fontein.de>
|
|
||||||
# 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()
|
|
|
@ -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 <felix@fontein.de>
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"include_symlinks": true,
|
|
||||||
"prefixes": [
|
|
||||||
"plugins/"
|
|
||||||
],
|
|
||||||
"output": "path-message"
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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()
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"include_symlinks": false,
|
|
||||||
"prefixes": [
|
|
||||||
"docs/docsite/rst/api-guide.rst",
|
|
||||||
"plugins/modules/"
|
|
||||||
],
|
|
||||||
"output": "path-line-column-message"
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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(['./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()
|
|
|
@ -1,9 +1,9 @@
|
||||||
docs/docsite/rst/api-guide.rst rstcheck
|
docs/docsite/rst/api-guide.rst rstcheck
|
||||||
docs/docsite/rst/quoting.rst rstcheck
|
docs/docsite/rst/quoting.rst rstcheck
|
||||||
docs/docsite/rst/ssh-guide.rst rstcheck
|
docs/docsite/rst/ssh-guide.rst rstcheck
|
||||||
update-docs.py compile-2.6
|
tests/update-docs.py compile-2.6
|
||||||
update-docs.py compile-2.7
|
tests/update-docs.py compile-2.7
|
||||||
update-docs.py compile-3.5
|
tests/update-docs.py compile-3.5
|
||||||
update-docs.py future-import-boilerplate
|
tests/update-docs.py future-import-boilerplate
|
||||||
update-docs.py metaclass-boilerplate
|
tests/update-docs.py metaclass-boilerplate
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
update-docs.py compile-2.6
|
tests/update-docs.py compile-2.6
|
||||||
update-docs.py compile-2.7
|
tests/update-docs.py compile-2.7
|
||||||
update-docs.py compile-3.5
|
tests/update-docs.py compile-3.5
|
||||||
update-docs.py future-import-boilerplate
|
tests/update-docs.py future-import-boilerplate
|
||||||
update-docs.py metaclass-boilerplate
|
tests/update-docs.py metaclass-boilerplate
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
tests/unit/compat/mock.py pylint:use-yield-from # suggested construct does not work with Python 2
|
|
||||||
|
|
1
tests/sanity/ignore-2.20.txt
Normal file
1
tests/sanity/ignore-2.20.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
tests/update-docs.py shebang
|
|
@ -1,9 +1,9 @@
|
||||||
docs/docsite/rst/api-guide.rst rstcheck
|
docs/docsite/rst/api-guide.rst rstcheck
|
||||||
docs/docsite/rst/quoting.rst rstcheck
|
docs/docsite/rst/quoting.rst rstcheck
|
||||||
docs/docsite/rst/ssh-guide.rst rstcheck
|
docs/docsite/rst/ssh-guide.rst rstcheck
|
||||||
update-docs.py compile-2.6
|
tests/update-docs.py compile-2.6
|
||||||
update-docs.py compile-2.7
|
tests/update-docs.py compile-2.7
|
||||||
update-docs.py compile-3.5
|
tests/update-docs.py compile-3.5
|
||||||
update-docs.py future-import-boilerplate
|
tests/update-docs.py future-import-boilerplate
|
||||||
update-docs.py metaclass-boilerplate
|
tests/update-docs.py metaclass-boilerplate
|
||||||
update-docs.py shebang
|
tests/update-docs.py shebang
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Copyright (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
|
|
||||||
# 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__'
|
|
|
@ -1,109 +0,0 @@
|
||||||
# Copyright (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
|
|
||||||
# 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
|
|
|
@ -1,25 +0,0 @@
|
||||||
# Copyright (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
|
|
||||||
# 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
|
|
|
@ -9,7 +9,7 @@ __metaclass__ = type
|
||||||
import os
|
import os
|
||||||
import json
|
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')
|
fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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.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
|
from ansible_collections.community.routeros.plugins.modules import api
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,8 +35,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
def test_module_fail_when_required_args_missing(self):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
set_module_args({})
|
with set_module_args({}):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -43,8 +44,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
@patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.path)
|
@patch('ansible_collections.community.routeros.plugins.modules.api.ROS_api_module.api_add_path', new=fake_ros_api.path)
|
||||||
def test_api_path(self):
|
def test_api_path(self):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
set_module_args(self.config_module_args.copy())
|
with set_module_args(self.config_module_args.copy()):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -54,8 +55,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['add'] = "name=unit_test_brige"
|
module_args['add'] = "name=unit_test_brige"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -65,8 +66,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['add'] = "name=unit_test_brige_exist"
|
module_args['add'] = "name=unit_test_brige_exist"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -77,8 +78,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['remove'] = "*A1"
|
module_args['remove'] = "*A1"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -88,8 +89,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['remove'] = "*A2"
|
module_args['remove'] = "*A2"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -100,8 +101,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['cmd'] = "add name=unit_test_brige_arbitrary"
|
module_args['cmd'] = "add name=unit_test_brige_arbitrary"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -111,8 +112,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['cmd'] = "add NONE_EXIST=unit_test_brige_arbitrary"
|
module_args['cmd'] = "add NONE_EXIST=unit_test_brige_arbitrary"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -123,8 +124,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['update'] = ".id=*A1 name=unit_test_brige"
|
module_args['update'] = ".id=*A1 name=unit_test_brige"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -134,8 +135,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['update'] = ".id=*A2 name=unit_test_brige"
|
module_args['update'] = ".id=*A2 name=unit_test_brige"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -146,8 +147,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['query'] = ".id name"
|
module_args['query'] = ".id name"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -162,8 +163,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['query'] = ".id other"
|
module_args['query'] = ".id other"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -174,8 +175,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['query'] = ".id name WHERE name == dummy_bridge_A2"
|
module_args['query'] = ".id name WHERE name == dummy_bridge_A2"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -188,8 +189,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['query'] = ".id name WHERE name != dummy_bridge_A2"
|
module_args['query'] = ".id name WHERE name != dummy_bridge_A2"
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -204,8 +205,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
module_args['extended_query'] = {
|
module_args['extended_query'] = {
|
||||||
'attributes': ['.id', 'name'],
|
'attributes': ['.id', 'name'],
|
||||||
}
|
}
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -222,8 +223,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
module_args['extended_query'] = {
|
module_args['extended_query'] = {
|
||||||
'attributes': ['.id', 'other'],
|
'attributes': ['.id', 'other'],
|
||||||
}
|
}
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -243,8 +244,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -266,8 +267,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -298,8 +299,8 @@ class TestRouterosApiModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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.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
|
from ansible_collections.community.routeros.plugins.modules import api_facts
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,8 +438,8 @@ class TestRouterosApiFactsModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
def test_module_fail_when_required_args_missing(self):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
set_module_args({})
|
with set_module_args({}):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -447,8 +448,8 @@ class TestRouterosApiFactsModule(ModuleTestCase):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
module_args = self.config_module_args.copy()
|
module_args = self.config_module_args.copy()
|
||||||
module_args['gather_subset'] = ['!foobar']
|
module_args['gather_subset'] = ['!foobar']
|
||||||
set_module_args(module_args)
|
with set_module_args(module_args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -456,8 +457,8 @@ class TestRouterosApiFactsModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_full_run(self):
|
def test_full_run(self):
|
||||||
with self.assertRaises(AnsibleExitJson) as exc:
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
set_module_args(self.config_module_args.copy())
|
with set_module_args(self.config_module_args.copy()):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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 (
|
from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import (
|
||||||
FakeLibRouterosError, fake_ros_api, massage_expected_result_data, create_fake_path,
|
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
|
from ansible_collections.community.routeros.plugins.modules import api_find_and_modify
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,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_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):
|
class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
|
|
||||||
|
@ -117,8 +164,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
def test_module_fail_when_required_args_missing(self):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
set_module_args({})
|
with set_module_args({}):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -136,8 +183,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'bar',
|
'comment': 'bar',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -155,8 +202,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'bar',
|
'comment': 'bar',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -173,8 +220,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'!comment': None,
|
'!comment': None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -190,8 +237,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'!comment': 'gone',
|
'!comment': 'gone',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -212,8 +259,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
'require_matches_min': 10,
|
'require_matches_min': 10,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -234,8 +281,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
'require_matches_min': 10,
|
'require_matches_min': 10,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -256,8 +303,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
'require_matches_max': 1,
|
'require_matches_max': 1,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -277,8 +324,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'name': 'bam',
|
'name': 'bam',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -303,8 +350,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'require_matches_min': 2,
|
'require_matches_min': 2,
|
||||||
'allow_no_matches': True,
|
'allow_no_matches': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -325,8 +372,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'values': {
|
'values': {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -349,8 +396,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': None,
|
'comment': None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -374,8 +421,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
'_ansible_diff': True,
|
'_ansible_diff': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -450,8 +497,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': None,
|
'comment': None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -502,8 +549,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': '',
|
'comment': '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -553,8 +600,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'!comment': None,
|
'!comment': None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -606,8 +653,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'!connection-state': None,
|
'!connection-state': None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -620,6 +667,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'protocol': 'icmp',
|
'protocol': 'icmp',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*3',
|
'.id': '*3',
|
||||||
|
@ -627,6 +676,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'chain': 'input',
|
'chain': 'input',
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*4',
|
'.id': '*4',
|
||||||
|
@ -634,6 +685,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'chain': 'input',
|
'chain': 'input',
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*7',
|
'.id': '*7',
|
||||||
|
@ -642,6 +695,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
'in-interface': 'wan',
|
'in-interface': 'wan',
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*8',
|
'.id': '*8',
|
||||||
|
@ -650,6 +705,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'connection-state': 'established',
|
'connection-state': 'established',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*9',
|
'.id': '*9',
|
||||||
|
@ -658,6 +715,8 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'connection-state': 'related',
|
'connection-state': 'related',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'.id': '*A',
|
'.id': '*A',
|
||||||
|
@ -666,7 +725,35 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
'comment': 'defconf',
|
'comment': 'defconf',
|
||||||
'connection-status': 'invalid',
|
'connection-status': 'invalid',
|
||||||
'disabled': False,
|
'disabled': False,
|
||||||
|
'log': False,
|
||||||
|
'log-prefix': '',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
self.assertEqual(result['match_count'], 3)
|
self.assertEqual(result['match_count'], 3)
|
||||||
self.assertEqual(result['modify_count'], 2)
|
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)
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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 (
|
from ansible_collections.community.routeros.tests.unit.plugins.modules.fake_api import (
|
||||||
FAKE_ROS_VERSION, FakeLibRouterosError, Key, fake_ros_api,
|
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
|
from ansible_collections.community.routeros.plugins.modules import api_info
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,8 +42,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
def test_module_fail_when_required_args_missing(self):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
set_module_args({})
|
with set_module_args({}):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -53,8 +54,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
args.update({
|
args.update({
|
||||||
'path': 'something invalid'
|
'path': 'something invalid'
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -68,8 +69,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
args.update({
|
args.update({
|
||||||
'path': 'ip dns static'
|
'path': 'ip dns static'
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -93,8 +94,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
args.update({
|
args.update({
|
||||||
'path': 'caps-man aaa',
|
'path': 'caps-man aaa',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -122,8 +123,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'caps-man aaa',
|
'path': 'caps-man aaa',
|
||||||
'hide_defaults': False,
|
'hide_defaults': False,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -155,8 +156,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'caps-man aaa',
|
'path': 'caps-man aaa',
|
||||||
'unfiltered': True,
|
'unfiltered': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -189,8 +190,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'ip firewall filter',
|
'path': 'ip firewall filter',
|
||||||
'handle_disabled': 'exclamation',
|
'handle_disabled': 'exclamation',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -278,8 +279,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'ip firewall filter',
|
'path': 'ip firewall filter',
|
||||||
'handle_disabled': 'null-value',
|
'handle_disabled': 'null-value',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -367,8 +368,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'ip firewall filter',
|
'path': 'ip firewall filter',
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -402,8 +403,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
'include_dynamic': True,
|
'include_dynamic': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -460,8 +461,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'interface list',
|
'path': 'interface list',
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -513,8 +514,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
'include_builtin': True,
|
'include_builtin': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -605,8 +606,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'path': 'ip dhcp-server lease',
|
'path': 'ip dhcp-server lease',
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -688,8 +689,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
args.update({
|
args.update({
|
||||||
'path': 'interface gre',
|
'path': 'interface gre',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -776,8 +777,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
'hide_defaults': False,
|
'hide_defaults': False,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -847,8 +848,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'handle_disabled': 'omit',
|
'handle_disabled': 'omit',
|
||||||
'restrict': [],
|
'restrict': [],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -899,8 +900,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
'values': ['forward'],
|
'values': ['forward'],
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -970,8 +971,8 @@ class TestRouterosApiInfoModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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 (
|
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,
|
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
|
from ansible_collections.community.routeros.plugins.modules import api_modify
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,8 +319,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
|
|
||||||
def test_module_fail_when_required_args_missing(self):
|
def test_module_fail_when_required_args_missing(self):
|
||||||
with self.assertRaises(AnsibleFailJson) as exc:
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
set_module_args({})
|
with set_module_args({}):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -331,8 +332,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'path': 'something invalid',
|
'path': 'something invalid',
|
||||||
'data': [],
|
'data': [],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -348,8 +349,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'foo': 'bar',
|
'foo': 'bar',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -366,8 +367,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'!comment': None,
|
'!comment': None,
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -383,8 +384,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'!disabled': None,
|
'!disabled': None,
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -400,8 +401,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'!comment': 'foo',
|
'!comment': 'foo',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -416,8 +417,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'name': None,
|
'name': None,
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -432,8 +433,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'interface': 'eth0',
|
'interface': 'eth0',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -448,8 +449,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'address': '192.168.88.1',
|
'address': '192.168.88.1',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -466,8 +467,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'address': '192.168.88.1',
|
'address': '192.168.88.1',
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['failed'], True)
|
self.assertEqual(result['failed'], True)
|
||||||
|
@ -498,8 +499,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -533,8 +534,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -556,8 +557,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -591,8 +592,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -656,8 +657,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -722,8 +723,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
],
|
],
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -785,8 +786,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -844,8 +845,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -903,8 +904,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -963,8 +964,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1017,8 +1018,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1077,8 +1078,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1128,8 +1129,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1164,8 +1165,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1212,8 +1213,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1285,8 +1286,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1340,8 +1341,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1363,8 +1364,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
],
|
],
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1386,8 +1387,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1426,8 +1427,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
],
|
],
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1466,8 +1467,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
],
|
],
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1507,8 +1508,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1551,8 +1552,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1587,8 +1588,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1621,8 +1622,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1676,8 +1677,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1729,8 +1730,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1785,8 +1786,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
'_ansible_check_mode': True,
|
'_ansible_check_mode': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1847,8 +1848,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1879,8 +1880,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -1911,8 +1912,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_entries_content': 'remove',
|
'handle_entries_content': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], True)
|
self.assertEqual(result['changed'], True)
|
||||||
|
@ -1969,8 +1970,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
@ -2005,8 +2006,8 @@ class TestRouterosApiModifyModule(ModuleTestCase):
|
||||||
'handle_absent_entries': 'remove',
|
'handle_absent_entries': 'remove',
|
||||||
'ensure_order': True,
|
'ensure_order': True,
|
||||||
})
|
})
|
||||||
set_module_args(args)
|
with set_module_args(args):
|
||||||
self.module.main()
|
self.module.main()
|
||||||
|
|
||||||
result = exc.exception.args[0]
|
result = exc.exception.args[0]
|
||||||
self.assertEqual(result['changed'], False)
|
self.assertEqual(result['changed'], False)
|
||||||
|
|
|
@ -8,9 +8,10 @@ __metaclass__ = type
|
||||||
|
|
||||||
import json
|
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.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
|
from .routeros_module import TestRouterosModule, load_fixture
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,54 +48,54 @@ class TestRouterosCommandModule(TestRouterosModule):
|
||||||
self.run_commands.side_effect = load_from_file
|
self.run_commands.side_effect = load_from_file
|
||||||
|
|
||||||
def test_command_simple(self):
|
def test_command_simple(self):
|
||||||
set_module_args(dict(commands=['/system resource print']))
|
with set_module_args(dict(commands=['/system resource print'])):
|
||||||
result = self.execute_module(changed=True)
|
result = self.execute_module(changed=True)
|
||||||
self.assertEqual(len(result['stdout']), 1)
|
self.assertEqual(len(result['stdout']), 1)
|
||||||
self.assertTrue('platform: "MikroTik"' in result['stdout'][0])
|
self.assertTrue('platform: "MikroTik"' in result['stdout'][0])
|
||||||
|
|
||||||
def test_command_multiple(self):
|
def test_command_multiple(self):
|
||||||
set_module_args(dict(commands=['/system resource print', '/system resource print']))
|
with set_module_args(dict(commands=['/system resource print', '/system resource print'])):
|
||||||
result = self.execute_module(changed=True)
|
result = self.execute_module(changed=True)
|
||||||
self.assertEqual(len(result['stdout']), 2)
|
self.assertEqual(len(result['stdout']), 2)
|
||||||
self.assertTrue('platform: "MikroTik"' in result['stdout'][0])
|
self.assertTrue('platform: "MikroTik"' in result['stdout'][0])
|
||||||
|
|
||||||
def test_command_wait_for(self):
|
def test_command_wait_for(self):
|
||||||
wait_for = 'result[0] contains "MikroTik"'
|
wait_for = 'result[0] contains "MikroTik"'
|
||||||
set_module_args(dict(commands=['/system resource print'], wait_for=wait_for))
|
with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)):
|
||||||
self.execute_module(changed=True)
|
self.execute_module(changed=True)
|
||||||
|
|
||||||
def test_command_wait_for_fails(self):
|
def test_command_wait_for_fails(self):
|
||||||
wait_for = 'result[0] contains "test string"'
|
wait_for = 'result[0] contains "test string"'
|
||||||
set_module_args(dict(commands=['/system resource print'], wait_for=wait_for))
|
with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for)):
|
||||||
self.execute_module(failed=True)
|
self.execute_module(failed=True)
|
||||||
self.assertEqual(self.run_commands.call_count, 10)
|
self.assertEqual(self.run_commands.call_count, 10)
|
||||||
|
|
||||||
def test_command_retries(self):
|
def test_command_retries(self):
|
||||||
wait_for = 'result[0] contains "test string"'
|
wait_for = 'result[0] contains "test string"'
|
||||||
set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, retries=2))
|
with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, retries=2)):
|
||||||
self.execute_module(failed=True)
|
self.execute_module(failed=True)
|
||||||
self.assertEqual(self.run_commands.call_count, 2)
|
self.assertEqual(self.run_commands.call_count, 2)
|
||||||
|
|
||||||
def test_command_match_any(self):
|
def test_command_match_any(self):
|
||||||
wait_for = ['result[0] contains "MikroTik"',
|
wait_for = ['result[0] contains "MikroTik"',
|
||||||
'result[0] contains "test string"']
|
'result[0] contains "test string"']
|
||||||
set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='any'))
|
with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='any')):
|
||||||
self.execute_module(changed=True)
|
self.execute_module(changed=True)
|
||||||
|
|
||||||
def test_command_match_all(self):
|
def test_command_match_all(self):
|
||||||
wait_for = ['result[0] contains "MikroTik"',
|
wait_for = ['result[0] contains "MikroTik"',
|
||||||
'result[0] contains "RB1100"']
|
'result[0] contains "RB1100"']
|
||||||
set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='all'))
|
with set_module_args(dict(commands=['/system resource print'], wait_for=wait_for, match='all')):
|
||||||
self.execute_module(changed=True)
|
self.execute_module(changed=True)
|
||||||
|
|
||||||
def test_command_match_all_failure(self):
|
def test_command_match_all_failure(self):
|
||||||
wait_for = ['result[0] contains "MikroTik"',
|
wait_for = ['result[0] contains "MikroTik"',
|
||||||
'result[0] contains "test string"']
|
'result[0] contains "test string"']
|
||||||
commands = ['/system resource print', '/system resource print']
|
commands = ['/system resource print', '/system resource print']
|
||||||
set_module_args(dict(commands=commands, wait_for=wait_for, match='all'))
|
with set_module_args(dict(commands=commands, wait_for=wait_for, match='all')):
|
||||||
self.execute_module(failed=True)
|
self.execute_module(failed=True)
|
||||||
|
|
||||||
def test_command_wait_for_2(self):
|
def test_command_wait_for_2(self):
|
||||||
wait_for = 'result[0] contains "wireless"'
|
wait_for = 'result[0] contains "wireless"'
|
||||||
set_module_args(dict(commands=['/system package print'], wait_for=wait_for))
|
with set_module_args(dict(commands=['/system package print'], wait_for=wait_for)):
|
||||||
self.execute_module(changed=True)
|
self.execute_module(changed=True)
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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.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
|
from .routeros_module import TestRouterosModule, load_fixture
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,8 +40,8 @@ class TestRouterosFactsModule(TestRouterosModule):
|
||||||
self.run_commands.side_effect = load_from_file
|
self.run_commands.side_effect = load_from_file
|
||||||
|
|
||||||
def test_facts_default(self):
|
def test_facts_default(self):
|
||||||
set_module_args(dict(gather_subset='default'))
|
with set_module_args(dict(gather_subset='default')):
|
||||||
result = self.execute_module()
|
result = self.execute_module()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result['ansible_facts']['ansible_net_hostname'], 'MikroTik'
|
result['ansible_facts']['ansible_net_hostname'], 'MikroTik'
|
||||||
)
|
)
|
||||||
|
@ -61,8 +62,8 @@ class TestRouterosFactsModule(TestRouterosModule):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_facts_hardware(self):
|
def test_facts_hardware(self):
|
||||||
set_module_args(dict(gather_subset='hardware'))
|
with set_module_args(dict(gather_subset='hardware')):
|
||||||
result = self.execute_module()
|
result = self.execute_module()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result['ansible_facts']['ansible_net_spacefree_mb'], 64921.6
|
result['ansible_facts']['ansible_net_spacefree_mb'], 64921.6
|
||||||
)
|
)
|
||||||
|
@ -77,8 +78,8 @@ class TestRouterosFactsModule(TestRouterosModule):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_facts_config(self):
|
def test_facts_config(self):
|
||||||
set_module_args(dict(gather_subset='config'))
|
with set_module_args(dict(gather_subset='config')):
|
||||||
result = self.execute_module()
|
result = self.execute_module()
|
||||||
self.assertIsInstance(
|
self.assertIsInstance(
|
||||||
result['ansible_facts']['ansible_net_config'], str
|
result['ansible_facts']['ansible_net_config'], str
|
||||||
)
|
)
|
||||||
|
@ -88,8 +89,8 @@ class TestRouterosFactsModule(TestRouterosModule):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_facts_interfaces(self):
|
def test_facts_interfaces(self):
|
||||||
set_module_args(dict(gather_subset='interfaces'))
|
with set_module_args(dict(gather_subset='interfaces')):
|
||||||
result = self.execute_module()
|
result = self.execute_module()
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
result['ansible_facts']['ansible_net_all_ipv4_addresses'][0], ['10.37.129.3', '10.37.0.0', '192.168.88.1']
|
result['ansible_facts']['ansible_net_all_ipv4_addresses'][0], ['10.37.129.3', '10.37.0.0', '192.168.88.1']
|
||||||
)
|
)
|
||||||
|
@ -118,8 +119,8 @@ class TestRouterosFactsModule(TestRouterosModule):
|
||||||
self.assertEqual(result, None)
|
self.assertEqual(result, None)
|
||||||
|
|
||||||
def test_facts_routing(self):
|
def test_facts_routing(self):
|
||||||
set_module_args(dict(gather_subset='routing'))
|
with set_module_args(dict(gather_subset='routing')):
|
||||||
result = self.execute_module()
|
result = self.execute_module()
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
result['ansible_facts']['ansible_net_bgp_peer']['iBGP_BRAS.TYRMA']['name'], ['iBGP_BRAS.TYRMA']
|
result['ansible_facts']['ansible_net_bgp_peer']['iBGP_BRAS.TYRMA']['name'], ['iBGP_BRAS.TYRMA']
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,54 +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 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
|
|
||||||
|
|
||||||
|
|
||||||
def set_module_args(args):
|
|
||||||
if '_ansible_remote_tmp' not in args:
|
|
||||||
args['_ansible_remote_tmp'] = '/tmp'
|
|
||||||
if '_ansible_keep_remote_files' not in args:
|
|
||||||
args['_ansible_keep_remote_files'] = False
|
|
||||||
|
|
||||||
args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
|
|
||||||
basic._ANSIBLE_ARGS = to_bytes(args)
|
|
||||||
|
|
||||||
|
|
||||||
class AnsibleExitJson(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AnsibleFailJson(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def exit_json(*args, **kwargs):
|
|
||||||
if 'changed' not in kwargs:
|
|
||||||
kwargs['changed'] = False
|
|
||||||
raise AnsibleExitJson(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def fail_json(*args, **kwargs):
|
|
||||||
kwargs['failed'] = True
|
|
||||||
raise AnsibleFailJson(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json)
|
|
||||||
self.mock_module.start()
|
|
||||||
self.mock_sleep = patch('time.sleep')
|
|
||||||
self.mock_sleep.start()
|
|
||||||
set_module_args({})
|
|
||||||
self.addCleanup(self.mock_module.stop)
|
|
||||||
self.addCleanup(self.mock_sleep.stop)
|
|
|
@ -4,4 +4,4 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
collections:
|
collections:
|
||||||
- ansible.netcommon
|
- community.internal_test_tools
|
||||||
|
|
29
update-docs.py → tests/update-docs.py
Executable file → Normal file
29
update-docs.py → tests/update-docs.py
Executable file → Normal file
|
@ -11,9 +11,6 @@ Updates DOCUMENTATION of modules using module_utils._api_data with the correct l
|
||||||
|
|
||||||
import sys
|
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 (
|
from ansible_collections.community.routeros.plugins.module_utils._api_data import (
|
||||||
PATHS,
|
PATHS,
|
||||||
join_path,
|
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:
|
with open(file, 'r', encoding='utf-8') as f:
|
||||||
lines = f.read().splitlines()
|
lines = f.read().splitlines()
|
||||||
begin_index = lines.index(begin_line)
|
begin_index = lines.index(begin_line)
|
||||||
end_index = lines.index(end_line, begin_index + 1)
|
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:]
|
new_lines = lines[:begin_index + 1] + [choice_line.format(choice=choice) for choice in path_choices] + lines[end_index:]
|
||||||
if lines != new_lines:
|
if lines == new_lines:
|
||||||
print(f'{file} has been updated')
|
return False
|
||||||
with open(file, 'w', encoding='utf-8') as f:
|
print(f'{file} has been updated')
|
||||||
f.write('\n'.join(new_lines) + '\n')
|
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])
|
path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if path_info.fully_understood])
|
||||||
|
|
||||||
|
changes = False
|
||||||
for file in MODULES:
|
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__':
|
if __name__ == '__main__':
|
||||||
main()
|
sys.exit(main(sys.argv[1:]))
|
Loading…
Add table
Add a link
Reference in a new issue