diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:04:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:04:41 +0000 |
commit | 975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch) | |
tree | 89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/openvswitch | |
parent | Initial commit. (diff) | |
download | ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip |
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/openvswitch')
82 files changed, 6766 insertions, 0 deletions
diff --git a/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml b/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml new file mode 100644 index 000000000..b425edcc2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml @@ -0,0 +1,15 @@ +--- +name: Code Coverage + +on: # yamllint disable-line rule:truthy + push: + pull_request: + branches: [ main ] + +jobs: + codecoverage: + uses: ansible-network/github_actions/.github/workflows/coverage_network_devices.yml@main + with: + collection_pre_install: >- + git+https://github.com/ansible-collections/ansible.utils.git + git+https://github.com/ansible-collections/ansible.netcommon.git diff --git a/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml b/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml new file mode 100644 index 000000000..428b1cf36 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml @@ -0,0 +1,32 @@ +name: Test collection + +concurrency: + group: ${{ github.head_ref }} + cancel-in-progress: true + +on: + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + changelog: + uses: ansible-network/github_actions/.github/workflows/changelog.yml@main + sanity: + uses: ansible-network/github_actions/.github/workflows/sanity.yml@main + unit-galaxy: + uses: ansible-network/github_actions/.github/workflows/unit_galaxy.yml@main + all_green: + if: ${{ always() }} + needs: + - changelog + - sanity + - unit-galaxy + runs-on: ubuntu-latest + steps: + - run: >- + python -c "assert set([ + '${{ needs.changelog.result }}', + '${{ needs.sanity.result }}', + '${{ needs.unit-galaxy.result }}', + ]) == {'success'}" diff --git a/ansible_collections/openvswitch/openvswitch/.gitignore b/ansible_collections/openvswitch/openvswitch/.gitignore new file mode 100644 index 000000000..172bf5786 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.gitignore @@ -0,0 +1 @@ +.tox diff --git a/ansible_collections/openvswitch/openvswitch/.isort.cfg b/ansible_collections/openvswitch/openvswitch/.isort.cfg new file mode 100644 index 000000000..a39e55e19 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.isort.cfg @@ -0,0 +1,4 @@ +[settings] +known_first_party=ansible_collections.openvswitch.openvswitch +line_length=100 +profile=black diff --git a/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml b/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml new file mode 100644 index 000000000..6ca2ad731 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +--- +repos: + - repo: https://github.com/ansible-network/collection_prep + rev: 1.1.1 + hooks: + - id: autoversion + - id: update-docs + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-merge-conflict + - id: debug-statements + - id: end-of-file-fixer + - id: no-commit-to-branch + - id: trailing-whitespace + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.0-alpha.9-for-vscode" + hooks: + - id: prettier + additional_dependencies: + - prettier + - prettier-plugin-toml + + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + args: ["--filter-files"] + + - repo: https://github.com/psf/black + rev: 23.3.0 + hooks: + - id: black diff --git a/ansible_collections/openvswitch/openvswitch/.prettierignore b/ansible_collections/openvswitch/openvswitch/.prettierignore new file mode 100644 index 000000000..5fbc1b8c8 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.prettierignore @@ -0,0 +1,17 @@ +# Stuff we don't want prettier to ever to look into +.*/ +coverage/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# A linked collection directory created by pytest-ansible-units +collections/ + +README.md diff --git a/ansible_collections/openvswitch/openvswitch/.yamllint b/ansible_collections/openvswitch/openvswitch/.yamllint new file mode 100644 index 000000000..3adaf90cf --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/.yamllint @@ -0,0 +1,15 @@ +--- +extends: default + +ignore: | + .tox + changelogs/* + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + line-length: disable diff --git a/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst b/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst new file mode 100644 index 000000000..a8e230d83 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst @@ -0,0 +1,129 @@ +==================================== +Openvswitch Collection Release Notes +==================================== + +.. contents:: Topics + + +v2.1.1 +====== + +Bugfixes +-------- + +- Fix galaxy version issue when installing this collection. + +Documentation Changes +--------------------- + +- Update module documentation and examples. + +v2.1.0 +====== + +Minor Changes +------------- + +- Allows read operation in openvswitch_db module(https://github.com/ansible-collections/openvswitch.openvswitch/pull/88) +- openvswitch modules got support for database socket parameter. + +v2.0.2 +====== + +Bugfixes +-------- + +- `openvswitch_bridge` - Fix idempotency for VLAN bridges + +v2.0.1 +====== + +Major Changes +------------- + +- By mistake we tagged the repo to 2.0.0 and as it wasn't intended and cannot be reverted we're releasing 2.0.1 to make the community aware of the major version update. + +v2.0.0 +====== + +Major Changes +------------- + +- There is no major changes for this particular release and it was tagged by mistake and cannot be reverted. + +v1.2.0 +====== + +Minor Changes +------------- + +- Allow setting multiple properties on a port (https://github.com/ansible-collections/openvswitch.openvswitch/issues/63). + +Bugfixes +-------- + +- Allow deleting key from table without specifying value (https://github.com/ansible-collections/openvswitch.openvswitch/issues/64). + +v1.1.0 +====== + +Minor Changes +------------- + +- openvswitch_bond - New module for managing Open vSwitch bonds (https://github.com/ansible-collections/openvswitch.openvswitch/pull/58). + +Bugfixes +-------- + +- Add version key to galaxy.yaml to work around ansible-galaxy bug (https://github.com/ansible-collections/openvswitch.openvswitch/issues/59) + +v1.0.5 +====== + +Minor Changes +------------- + +- Regenerated docs, add description to galaxy.yml and linked changelog to README (https://github.com/ansible-collections/openvswitch.openvswitch/pull/53). + +v1.0.4 +====== + +Release Summary +--------------- + +Rereleased 1.0.3 with updated changelog. + +v1.0.3 +====== + +Release Summary +--------------- + +Released for testing. + +v1.0.2 +====== + +Release Summary +--------------- + +Rereleased 1.0.1 with updated changelog. + +v1.0.1 +====== + +Bugfixes +-------- + +- Makes sure that docstring and argspec are in sync and removes sanity ignores (https://github.com/ansible-collections/openvswitch.openvswitch/pull/46). +- Update docs after sanity fixes to modules. + +v1.0.0 +====== + +New Modules +----------- + +- openvswitch_bridge - Manage Open vSwitch bridges +- openvswitch_db - Configure open vswitch database. +- openvswitch_port - Manage Open vSwitch ports diff --git a/ansible_collections/openvswitch/openvswitch/FILES.json b/ansible_collections/openvswitch/openvswitch/FILES.json new file mode 100644 index 000000000..d1f5faaad --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/FILES.json @@ -0,0 +1,782 @@ +{ + "files": [ + { + "name": ".", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows/codecoverage.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a56c8aba05b81d2e1d6575b37963f40df663387030de5eaac6f5c9dfd7af54f1", + "format": 1 + }, + { + "name": ".github/workflows/test.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "68f1dab3d706336656fd2e69665f0f0baea7952aeb9ec88c04efb828c5a1e748", + "format": 1 + }, + { + "name": "changelogs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/.plugin-cache.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7ed118736237c922e32159f3adb4035237ca8e56271197d4fa49e9baa2b6f408", + "format": 1 + }, + { + "name": "changelogs/changelog.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3b58f26fb5ec8dd709538fc569fd66d3409e31a9ee0daaece218cf9b0ee9dd4b", + "format": 1 + }, + { + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2adb276dfb7fe5754f0ed71a5678bf5fe38cfb7faf137f8087d7cd7be9ab0968", + "format": 1 + }, + { + "name": "docs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "docs/openvswitch.openvswitch.openvswitch_bond_module.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eebe22da580707acab765f0a37fea28dd24740594a9efaa3b754474b45c9dd7a", + "format": 1 + }, + { + "name": "docs/openvswitch.openvswitch.openvswitch_bridge_module.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8b49055378c201a883f16920e2e589ea5af5b6b95a1ec8376bf1b79324699e9e", + "format": 1 + }, + { + "name": "docs/openvswitch.openvswitch.openvswitch_db_module.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f04f4804f09779c06564557974dcf9fb764d86f23a83fbeaa8b00f1b996bbd28", + "format": 1 + }, + { + "name": "docs/openvswitch.openvswitch.openvswitch_port_module.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f9dfacacb82c5411193085bbcec480593612c9c5b2ca6ef2d3c26fbd8edc862e", + "format": 1 + }, + { + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta/runtime.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6eaf1c23aa84c677ad9d7b9bfb1033a07ebc7ce3ea2f693e79e844ef1bc86574", + "format": 1 + }, + { + "name": "plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/modules/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/modules/openvswitch_bond.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "da013d93cbd467a08ea02429a3a2289eac85c5b10dc51caab94d046597aa9fa1", + "format": 1 + }, + { + "name": "plugins/modules/openvswitch_bridge.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "38952dd15bbfa23f45c406dc81c79ad83d8bb972aa88922b833809f4b21a8ce8", + "format": 1 + }, + { + "name": "plugins/modules/openvswitch_db.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8ff4334f056b584d937a1de01a754953bd25ad07365914bcd71e9dab8e810233", + "format": 1 + }, + { + "name": "plugins/modules/openvswitch_port.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5b69b48f8a1fd003ed76ac6a32701a050a6f07b24aea8f3dc3469f74f0d14c64", + "format": 1 + }, + { + "name": "tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/defaults/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "665288590cd4226da42511817f09ccdfc92df36c9621583cd2c82919af295c5a", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/meta/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8030d202f0d4ed045738a0be23a2b00abca712f250fd05504f67f4083806e70d", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "864fdb64c38a190f819cfdcb18fd2bd93910347d8afc0e50bebf376aa0405800", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/tests/basic.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "71355de14b7606ddc4150315db87f07d85febb47a92b9414e5a538d9adc9941a", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_bridge/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "796f43c1ce3f6a1461bdb8ff0f62ddecd2ab76d2131364d58279a9e066119006", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/defaults/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "665288590cd4226da42511817f09ccdfc92df36c9621583cd2c82919af295c5a", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/meta/main.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8030d202f0d4ed045738a0be23a2b00abca712f250fd05504f67f4083806e70d", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "864fdb64c38a190f819cfdcb18fd2bd93910347d8afc0e50bebf376aa0405800", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/tests/basic.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1df8b2b57b13c7ad3e6f65e9d77e4c8ebeeec19c3543f76cb4b95dc29b5fc7bc", + "format": 1 + }, + { + "name": "tests/integration/targets/openvswitch_db/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "796f43c1ce3f6a1461bdb8ff0f62ddecd2ab76d2131364d58279a9e066119006", + "format": 1 + }, + { + "name": "tests/integration/targets/prepare_ovs_tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/prepare_ovs_tests/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/prepare_ovs_tests/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1bab35091b1edea841526465500fa96b65e5ac8dd0edd3efd4a8e8fe2a6ae42b", + "format": 1 + }, + { + "name": "tests/integration/network-integration.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d67b11263a8f50b30bf43c7c2b4bdd8dc4f173f0b5dd22761311360dfbd56a1d", + "format": 1 + }, + { + "name": "tests/integration/target-prefixes.network", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a60524cedd48d85c64c8a6be73270ec86302fcde54829a94c5240577af9cd29", + "format": 1 + }, + { + "name": "tests/sanity", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.10.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.9.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/compat", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/compat/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/compat/mock.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c1027e053a21d6e19f021cd022137ac984433b9066fabaa5abe1cd67b842d880", + "format": 1 + }, + { + "name": "tests/unit/compat/unittest.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3ed698b1faec43d87a2c1ebcb15a2aae48b09ff355bb9a598e5f5a1c928dbb30", + "format": 1 + }, + { + "name": "tests/unit/mock", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/mock/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/mock/loader.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a3719aed31d2c5f5392c699a49f2ac3e93e499394d7cfdf7e92cbcb5fbda199", + "format": 1 + }, + { + "name": "tests/unit/mock/path.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c225b58b136e2043c7f7b6e8f1fe236826de312e8e776157c35ffa95f33ac19d", + "format": 1 + }, + { + "name": "tests/unit/mock/procenv.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee2694a844ac94a6ca0ff89f4201799e6130140dafaa7c160e0d8a18867dfb93", + "format": 1 + }, + { + "name": "tests/unit/mock/vault_helper.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f9e3bd3e1a1cb27f74017fedc58266ba5958e1dfaf1e1a83d2d36176f22c4308", + "format": 1 + }, + { + "name": "tests/unit/mock/yaml_helper.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8e16dc5bf20c7fcd862f3c30b2752954ccc65c6bae3066ff048a338f57e19901", + "format": 1 + }, + { + "name": "tests/unit/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/network", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fb4d8c7a525630ab89af2b8f6b3b51f65877f20a569a87fc33bdbe1c3922f929", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c645f32418aa5d29ef2019dc8d3a86dd3d8d728b20525e06f1e8f0b77f453a8a", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "64f8590dc1c153a7569418973e62755013551bcf78b624ed4c6f766005a55a36", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c0dac1db3bfc4b4dbf889edb777f280d8f3f8e0d11f500fde7bf387645386d4a", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b9fe20d613e9e0e526b6044cd92d2b9766922a50cf722bb0766c7375d472942c", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c0dac1db3bfc4b4dbf889edb777f280d8f3f8e0d11f500fde7bf387645386d4a", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c645f32418aa5d29ef2019dc8d3a86dd3d8d728b20525e06f1e8f0b77f453a8a", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2968b4d67997fded3a924b3ad98d983facfe51861d738bc9928aa687e9340a86", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4dd854aba69453d0c5d442b39eebde7036f3834ed1c126f1cfad223c58a872d4", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "074e61c3d4ff7f1666fe08b48b30a75b071a0b7b014a8d619dfdab48c974d43e", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "86bfabba396d54e82162037801585a124cc7c9a19489a974b01f1cb2ee0a39db", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/ovs_module.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "857ad60b3cc7654fc20888fdde42271493cfc3db5728fd8b8572ce282ee82a81", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/test_openvswitch_bond.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4e3dea7c472eda27beab0be4c8421e3bb75a75f63edd537dcfbf3d35d3de2f18", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/test_openvswitch_bridge.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4f6544a71b2b596a96be66a8ca017c57c7d24560a06146058694a5112717f2fd", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/test_openvswitch_db.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "54f7be5c873c58a17b2e3d1b5d9bc3b89a7e8364826dae9087148617350ca2eb", + "format": 1 + }, + { + "name": "tests/unit/modules/network/ovs/test_openvswitch_port.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c4082f545ccd3f977d30305be413463fb3027275173d806294ae033e14e20d8", + "format": 1 + }, + { + "name": "tests/unit/modules/network/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/modules/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/modules/conftest.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "91a7af4f26197c9c55a48ad00d004a56f8ba43604cb83ff8d1da857a99526a75", + "format": 1 + }, + { + "name": "tests/unit/modules/utils.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fa8c30c6423b5a307d4d47f818dd037cecb9781a15fb26543fd2125b0ab8fa29", + "format": 1 + }, + { + "name": "tests/unit/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "49ba996dc4735c3463e9af561344346dfae14bcc1a68096ce78364b377f0df1f", + "format": 1 + }, + { + "name": "tests/.gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600", + "format": 1 + }, + { + "name": ".gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ddc61d479977d318682280fa2b18bcb6cb9a1b0e0e7897cea3d14d5c8d222e68", + "format": 1 + }, + { + "name": ".isort.cfg", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5a1cbc1860f66ffbd0601a7d3f09d0d05c7c204260e34b00b5a3fc3c9c66dcc4", + "format": 1 + }, + { + "name": ".pre-commit-config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "51b246b858aab8696cbf5cfca18dc0dc223351bc919d8cb595695f5edbd70f62", + "format": 1 + }, + { + "name": ".prettierignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d4794efd30dbced939a50b3dd436b231470bc09e7e69ed28713aa1867b184fd7", + "format": 1 + }, + { + "name": ".yamllint", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "827ef9e031ecdcaf137be239d33ef93fcbbc3611cbb6b30b0e507d0e03373d0e", + "format": 1 + }, + { + "name": "CHANGELOG.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f9fccb4667a56127bc19dede309674e6d5534839f1c7a93aef2aaba09e9d3063", + "format": 1 + }, + { + "name": "LICENSE", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "91272b3132e10b4e6ce93e00ee5fea0fd97ee72338913d7c2dbf84bec8270981", + "format": 1 + }, + { + "name": "bindep.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bc4c11f2eaa67b38574c8ab4052deee3644c88b1a45fd9c1153cc6c447daac7b", + "format": 1 + }, + { + "name": "codecov.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d7119b3a96ece7bcd2df6e851e7e19783049f280918a801344d502c6ada4e582", + "format": 1 + }, + { + "name": "pyproject.toml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1cb6a45dfa2625123890b93ad7fdc156b063c16e8ae6dba11511a1d1986b0fcc", + "format": 1 + }, + { + "name": "requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "test-requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6bc12fd99094693035494ca012b5acac80bbbbb2824f0a60a3b2c2d94dd048cc", + "format": 1 + }, + { + "name": "tox.ini", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "76b579ff04d1b4f49495fccbd86b2f682a3050b7092c7f92af3be1b9396d76e7", + "format": 1 + } + ], + "format": 1 +}
\ No newline at end of file diff --git a/ansible_collections/openvswitch/openvswitch/LICENSE b/ansible_collections/openvswitch/openvswitch/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/ansible_collections/openvswitch/openvswitch/MANIFEST.json b/ansible_collections/openvswitch/openvswitch/MANIFEST.json new file mode 100644 index 000000000..a4a039a20 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/MANIFEST.json @@ -0,0 +1,33 @@ +{ + "collection_info": { + "namespace": "openvswitch", + "name": "openvswitch", + "version": "2.1.1", + "authors": [ + "Ansible Network Community (ansible-network)" + ], + "readme": "README.md", + "tags": [ + "networking", + "vswitch", + "bridge", + "vlan" + ], + "description": "Ansible Network Collection for Open vSwitch", + "license": [], + "license_file": "LICENSE", + "dependencies": {}, + "repository": "https://github.com/ansible-collections/openvswitch.openvswitch", + "documentation": null, + "homepage": null, + "issues": "https://github.com/ansible-collections/openvswitch.openvswitch/issues" + }, + "file_manifest_file": { + "name": "FILES.json", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a3c4f61b8611e8f26f8749b1408367e4142def8d001e13858d1c36414f54d47d", + "format": 1 + }, + "format": 1 +}
\ No newline at end of file diff --git a/ansible_collections/openvswitch/openvswitch/README.md b/ansible_collections/openvswitch/openvswitch/README.md new file mode 100644 index 000000000..1687293a0 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/README.md @@ -0,0 +1,109 @@ + + +# Open vSwitch Collection +[![CI](https://zuul-ci.org/gated.svg)](https://dashboard.zuul.ansible.com/t/ansible/project/github.com/ansible-collections/openvswitch.openvswitch) <!--[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/vyos)](https://codecov.io/gh/ansible-collections/openvswitch.openvswitch)--> + +The Open vSwitch collection includes a variety of Ansible content to help automate the management of Open vSwitch. + +<!--start requires_ansible--> +## Ansible version compatibility + +This collection has been tested against following Ansible versions: **>=2.9.10**. + +For collections that support Ansible 2.9, please ensure you update your `network_os` to use the +fully qualified collection name (for example, `cisco.ios.ios`). +Plugins and modules within a collection may be tested with only specific Ansible versions. +A collection may contain metadata that identifies these versions. +PEP440 is the schema used to describe the versions of Ansible. +<!--end requires_ansible--> + +### Supported connections +The Open vSwitch collection supports local connections only. + +## Included content + +Click the ``Content`` button to see the list of content included in this collection. + +<!--start collection content--> +### Modules +Name | Description +--- | --- +[openvswitch.openvswitch.openvswitch_bond](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_bond_module.rst)|Manage Open vSwitch bonds +[openvswitch.openvswitch.openvswitch_bridge](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst)|Manage Open vSwitch bridges +[openvswitch.openvswitch.openvswitch_db](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_db_module.rst)|Configure open vswitch database. +[openvswitch.openvswitch.openvswitch_port](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_port_module.rst)|Manage Open vSwitch ports + +<!--end collection content--> + +## Installing this collection + +You can install the Open vSwitch collection with the Ansible Galaxy CLI: + + ansible-galaxy collection install openvswitch.openvswitch + +You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format: + +```yaml +--- +collections: + - name: openvswitch.openvswitch +``` +## Using this collection + +You can call modules by their Fully Qualified Collection Namespace (FQCN), such as `openvswitch.openvswitch.openvswitch_port`. +The following example task replaces configuration changes in the existing configuration on a Open vSwitch network device, using the FQCN: + +```yaml +--- + - name: Creates port eth2 on bridge br-ex + openvswitch.openvswitch.openvswitch_port: + bridge: br-ex + port: eth2 + state: present +``` + +**NOTE**: For Ansible 2.9, you may not see deprecation warnings when you run your playbooks with this collection. Use this documentation to track when a module is deprecated. + + +### See Also: + +* [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. + +## Contributing to this collection + +We welcome community contributions to this collection. If you find problems, please open an issue or create a PR against the [Open vSwitch collection repository](https://github.com/ansible-collections/openvswitch.openvswitch). See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details. + +You can also join us on: + +- IRC - the ``#ansible-network`` [irc.libera.chat](https://libera.chat/) channel +- Slack - https://ansiblenetwork.slack.com + +See the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for details on contributing to Ansible. + +### Code of Conduct +This collection follows the Ansible project's +[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html). +Please read and familiarize yourself with this document. + + +## Changelogs + +Release notes are available [here](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/changelogs/CHANGELOG.rst). + +## Roadmap + +<!-- Optional. Include the roadmap for this collection, and the proposed release/versioning strategy so users can anticipate the upgrade/update cycle. --> + +## More information + +- [Ansible network resources](https://docs.ansible.com/ansible/latest/network/getting_started/network_resources.html) +- [Ansible Collection overview](https://github.com/ansible-collections/overview) +- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) +- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) +- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) + +## Licensing + +GNU General Public License v3.0 or later. + +See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. diff --git a/ansible_collections/openvswitch/openvswitch/bindep.txt b/ansible_collections/openvswitch/openvswitch/bindep.txt new file mode 100644 index 000000000..a8b2ccc40 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/bindep.txt @@ -0,0 +1,9 @@ +# This is a cross-platform list tracking distribution packages needed by tests; +# see https://docs.openstack.org/infra/bindep/ for additional information. + +gcc-c++ [doc test platform:rpm] +libyaml-devel [test platform:rpm] +libyaml-dev [test platform:dpkg] +libssh-devel [test platform:rpm] +libffi-devel [test platform:rpm] +openssl-devel [test platform:rpm] diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml new file mode 100644 index 000000000..f7b35680d --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml @@ -0,0 +1,39 @@ +objects: + role: {} +plugins: + become: {} + cache: {} + callback: {} + cliconf: {} + connection: {} + filter: {} + httpapi: {} + inventory: {} + lookup: {} + module: + openvswitch_bond: + description: Manage Open vSwitch bonds + name: openvswitch_bond + namespace: "" + version_added: 1.0.0 + openvswitch_bridge: + description: Manage Open vSwitch bridges + name: openvswitch_bridge + namespace: "" + version_added: 1.0.0 + openvswitch_db: + description: Configure open vswitch database. + name: openvswitch_db + namespace: "" + version_added: 1.0.0 + openvswitch_port: + description: Manage Open vSwitch ports + name: openvswitch_port + namespace: "" + version_added: 1.0.0 + netconf: {} + shell: {} + strategy: {} + test: {} + vars: {} +version: 2.1.1 diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml new file mode 100644 index 000000000..17f610e11 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml @@ -0,0 +1,114 @@ +ancestor: null +releases: + 1.0.0: + modules: + - description: Manage Open vSwitch bridges + name: openvswitch_bridge + namespace: "" + - description: Configure open vswitch database. + name: openvswitch_db + namespace: "" + - description: Manage Open vSwitch ports + name: openvswitch_port + namespace: "" + release_date: "2020-06-23" + 1.0.1: + changes: + bugfixes: + - Makes sure that docstring and argspec are in sync and removes sanity ignores + (https://github.com/ansible-collections/openvswitch.openvswitch/pull/46). + - Update docs after sanity fixes to modules. + fragments: + - remove_ignores.yaml + - update_docs.yaml + release_date: "2020-08-03" + 1.0.2: + changes: + release_summary: Rereleased 1.0.1 with updated changelog. + fragments: + - 1.0.2.yaml + release_date: "2020-08-07" + 1.0.3: + changes: + release_summary: Released for testing. + fragments: + - 1.0.3.yaml + release_date: "2020-08-07" + 1.0.4: + changes: + release_summary: Rereleased 1.0.3 with updated changelog. + fragments: + - 1.0.4.yaml + release_date: "2020-08-08" + 1.0.5: + changes: + minor_changes: + - Regenerated docs, add description to galaxy.yml and linked changelog to README + (https://github.com/ansible-collections/openvswitch.openvswitch/pull/53). + fragments: + - fixes_to_readme_and_doc.yaml + release_date: "2020-08-28" + 1.1.0: + changes: + bugfixes: + - Add version key to galaxy.yaml to work around ansible-galaxy bug (https://github.com/ansible-collections/openvswitch.openvswitch/issues/59) + minor_changes: + - openvswitch_bond - New module for managing Open vSwitch bonds (https://github.com/ansible-collections/openvswitch.openvswitch/pull/58). + fragments: + - 1-openvswitch_bond-new-module.yaml + - fix_download_git.yaml + release_date: "2020-11-26" + 1.2.0: + changes: + bugfixes: + - Allow deleting key from table without specifying value (https://github.com/ansible-collections/openvswitch.openvswitch/issues/64). + minor_changes: + - Allow setting multiple properties on a port (https://github.com/ansible-collections/openvswitch.openvswitch/issues/63). + fragments: + - fix_openvswitch_db.yaml + - fix_openvswitch_port.yaml + release_date: "2021-02-24" + 2.0.0: + changes: + major_changes: + - There is no major changes for this particular release and it was tagged by + mistake and cannot be reverted. + release_date: "2021-02-24" + 2.0.1: + changes: + major_changes: + - By mistake we tagged the repo to 2.0.0 and as it wasn't intended and cannot + be reverted we're releasing 2.0.1 to make the community aware of the major + version update. + release_date: "2021-03-03" + 2.0.2: + changes: + bugfixes: + - "`openvswitch_bridge` - Fix idempotency for VLAN bridges" + fragments: + - 69-remove_tests_sanity_requirements.yml + - fix_validate_modules.yaml + - fix_vlan_bridge_idempotency.yaml + - pylint_fixes.yaml + release_date: "2021-09-24" + 2.1.0: + changes: + minor_changes: + - Allows read operation in openvswitch_db module(https://github.com/ansible-collections/openvswitch.openvswitch/pull/88) + - openvswitch modules got support for database socket parameter. + fragments: + - 84-ovs-modules-database-socket.yaml + - openvswitch_db_read.yaml + release_date: "2021-12-07" + 2.1.1: + changes: + bugfixes: + - Fix galaxy version issue when installing this collection. + doc_changes: + - Update module documentation and examples. + fragments: + - black.yaml + - fix.yaml + - galaxy.yml + - gha.yaml + release_date: "2023-04-27" diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml new file mode 100644 index 000000000..f6f3c1fa9 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml @@ -0,0 +1,32 @@ +changelog_filename_template: ../CHANGELOG.rst +changelog_filename_version_depth: 0 +changes_file: changelog.yaml +changes_format: combined +keep_fragments: false +mention_ancestor: true +new_plugins_after_name: removed_features +notesdir: fragments +prelude_section_name: release_summary +prelude_section_title: Release Summary +flatmap: true +sections: + - - major_changes + - Major Changes + - - minor_changes + - Minor Changes + - - breaking_changes + - Breaking Changes / Porting Guide + - - deprecated_features + - Deprecated Features + - - removed_features + - Removed Features (previously deprecated) + - - security_fixes + - Security Fixes + - - bugfixes + - Bugfixes + - - known_issues + - Known Issues + - - doc_changes + - Documentation Changes +title: Openvswitch Collection +trivial_section_name: trivial diff --git a/ansible_collections/openvswitch/openvswitch/codecov.yml b/ansible_collections/openvswitch/openvswitch/codecov.yml new file mode 100644 index 000000000..816cb4409 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/codecov.yml @@ -0,0 +1,10 @@ +--- +codecov: + require_ci_to_pass: true +comment: false +coverage: + status: + patch: false + project: + default: + threshold: 0.3% diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst new file mode 100644 index 000000000..5ebc2edfa --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst @@ -0,0 +1,341 @@ +.. _openvswitch.openvswitch.openvswitch_bond_module: + + +**************************************** +openvswitch.openvswitch.openvswitch_bond +**************************************** + +**Manage Open vSwitch bonds** + + +Version added: 1.0.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- Manage Open vSwitch bonds and associated options. + + + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- ovs-vsctl + + +Parameters +---------- + +.. raw:: html + + <table border=0 cellpadding=0 class="documentation-table"> + <tr> + <th colspan="1">Parameter</th> + <th>Choices/<font color="blue">Defaults</font></th> + <th width="100%">Comments</th> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bond_downdelay</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + </td> + <td> + <div>Number of milliseconds a link must be down to be deactivated to prevent flapping.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bond_mode</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li>active-backup</li> + <li>balance-tcp</li> + <li>balance-slb</li> + </ul> + </td> + <td> + <div>Sets the bond mode</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bond_updelay</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + </td> + <td> + <div>Number of milliseconds a link must be up to be activated to prevent flapping.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bridge</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Name of bridge to manage</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>database_socket</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Path/ip to datbase socket to use</div> + <div>Default path is used if not specified</div> + <div>Path should start with 'unix:' prefix</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>external_ids</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">dictionary</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">{}</div> + </td> + <td> + <div>Dictionary of external_ids applied to a port.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>interfaces</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">list</span> + / <span style="color: purple">elements=string</span> + </div> + </td> + <td> + </td> + <td> + <div>List of interfaces to add to the bond</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>lacp</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li>active</li> + <li>passive</li> + <li>off</li> + </ul> + </td> + <td> + <div>Sets LACP mode</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>other_config</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">dictionary</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">{}</div> + </td> + <td> + <div>Dictionary of other_config applied to a port.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>port</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Name of port to manage on the bridge</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>set</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">list</span> + / <span style="color: purple">elements=string</span> + </div> + </td> + <td> + </td> + <td> + <div>Sets one or more properties on a port.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>state</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li><div style="color: blue"><b>present</b> ←</div></li> + <li>absent</li> + </ul> + </td> + <td> + <div>Whether the port should exist</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>timeout</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">5</div> + </td> + <td> + <div>How long to wait for ovs-vswitchd to respond in seconds</div> + </td> + </tr> + </table> + <br/> + + + + +Examples +-------- + +.. code-block:: yaml + + - name: Create an active-backup bond using eth4 and eth5 on bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + state: present + - name: Delete the bond from bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + state: absent + - name: Create an active LACP bond using eth4 and eth5 on bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + lacp: active + state: present + # NOTE: other_config values of integer type must be represented + # as literal strings + - name: Configure bond with miimon link monitoring at 100 millisecond intervals + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + bond_updelay: 100 + bond_downdelay: 100 + state: present + args: + other_config: + bond-detect-mode: miimon + bond-miimon-interval: '"100"' + - name: Create an active LACP bond using DPDK interfaces + openvswitch.openvswitch.openvswitch_bond: + bridge: br-provider + port: dpdkbond + interfaces: + - "0000:04:00.0" + - "0000:04:00.1" + lacp: active + set: + - "interface 0000:04:00.0 type=dpdk options:dpdk-devargs=0000:04:00.0" + - "interface 0000:04:00.1 type=dpdk options:dpdk-devargs=0000:04:00.1" + state: present + - name: Create an active-backup bond using eth4 and eth5 on bridge br-ex in second OVS database + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + state: present + database_socket: unix:/opt/second.sock + + + + +Status +------ + + +Authors +~~~~~~~ + +- James Denton (@busterswt) diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst new file mode 100644 index 000000000..6432d61f1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst @@ -0,0 +1,232 @@ +.. _openvswitch.openvswitch.openvswitch_bridge_module: + + +****************************************** +openvswitch.openvswitch.openvswitch_bridge +****************************************** + +**Manage Open vSwitch bridges** + + +Version added: 1.0.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- Manage Open vSwitch bridges + + + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- ovs-vsctl + + +Parameters +---------- + +.. raw:: html + + <table border=0 cellpadding=0 class="documentation-table"> + <tr> + <th colspan="1">Parameter</th> + <th>Choices/<font color="blue">Defaults</font></th> + <th width="100%">Comments</th> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bridge</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Name of bridge or fake bridge to manage</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>database_socket</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Path/ip to datbase socket to use</div> + <div>Default path is used if not specified</div> + <div>Path should start with 'unix:' prefix</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>external_ids</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">dictionary</span> + </div> + </td> + <td> + </td> + <td> + <div>A dictionary of external-ids. Omitting this parameter is a No-op. To clear all external-ids pass an empty value.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>fail_mode</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Set bridge fail-mode. The default value (None) is a No-op.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>parent</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Bridge parent of the fake bridge to manage</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>set</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Run set command after bridge configuration. This parameter is non-idempotent, play will always return <em>changed</em> state if present</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>state</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li><div style="color: blue"><b>present</b> ←</div></li> + <li>absent</li> + </ul> + </td> + <td> + <div>Whether the bridge should exist</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>timeout</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">5</div> + </td> + <td> + <div>How long to wait for ovs-vswitchd to respond</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>vlan</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + </td> + <td> + <div>The VLAN id of the fake bridge to manage (must be between 0 and 4095). This parameter is required if <em>parent</em> parameter is set.</div> + </td> + </tr> + </table> + <br/> + + + + +Examples +-------- + +.. code-block:: yaml + + # Create a bridge named br-int + - openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + state: present + + # Create a fake bridge named br-int within br-parent on the VLAN 405 + - openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + parent: br-parent + vlan: 405 + state: present + + # Create an integration bridge + - openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + state: present + fail_mode: secure + args: + external_ids: + bridge-id: br-int + # Create a bridge named br0 in database with socket at /opt/second.sock + - openvswitch.openvswitch.openvswitch_bridge: + bridge: br0 + state: present + database_socket: unix:/opt/second.sock + + + + +Status +------ + + +Authors +~~~~~~~ + +- David Stygstra (@stygstra) diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst new file mode 100644 index 000000000..d8bf4ae72 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst @@ -0,0 +1,305 @@ +.. _openvswitch.openvswitch.openvswitch_db_module: + + +************************************** +openvswitch.openvswitch.openvswitch_db +************************************** + +**Configure open vswitch database.** + + +Version added: 1.0.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- Set column values in record in database table. + + + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- ovs-vsctl >= 2.3.3 + + +Parameters +---------- + +.. raw:: html + + <table border=0 cellpadding=0 class="documentation-table"> + <tr> + <th colspan="1">Parameter</th> + <th>Choices/<font color="blue">Defaults</font></th> + <th width="100%">Comments</th> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>col</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Identifies the column in the record.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>database_socket</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Path/ip to datbase socket to use</div> + <div>Default path is used if not specified</div> + <div>Path should start with 'unix:' prefix</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>key</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Identifies the key in the record column, when the column is a map type.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>record</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Identifies the record in the table.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>state</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li><div style="color: blue"><b>present</b> ←</div></li> + <li>absent</li> + <li>read</li> + </ul> + </td> + <td> + <div>Configures the state of the key. When set to <em>present</em>, the <em>key</em> and <em>value</em> pair will be set on the <em>record</em> and when set to <em>absent</em> the <em>key</em> will not be set.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>table</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Identifies the table in the database.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>timeout</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">5</div> + </td> + <td> + <div>How long to wait for ovs-vswitchd to respond</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>value</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Expected value for the table, record, column and key.</div> + </td> + </tr> + </table> + <br/> + + + + +Examples +-------- + +.. code-block:: yaml + + # Increase the maximum idle time to 50 seconds before pruning unused kernel + # rules. + - openvswitch.openvswitch.openvswitch_db: + table: open_vswitch + record: . + col: other_config + key: max-idle + value: 50000 + + # Disable in band copy + - openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-int + col: other_config + key: disable-in-band + value: true + + # Remove in band key + - openvswitch.openvswitch.openvswitch_db: + state: present + table: Bridge + record: br-int + col: other_config + key: disable-in-band + + # Mark port with tag 10 + - openvswitch.openvswitch.openvswitch_db: + table: Port + record: port0 + col: tag + value: 10 + + # Mark port with tag 10 for OVSDB with socket in /opt/second.sock + - openvswitch.openvswitch.openvswitch_db: + table: Port + record: port0 + col: tag + value: 10 + database_socket: unix:/opt/second.sock + + # Get interface statistics + - openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: statistics + + # Get tx_packets value + - openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: statistics + key: tx_packets + + # Get mtu value + - openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: mtu + + + +Return Values +------------- +Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module: + +.. raw:: html + + <table border=0 cellpadding=0 class="documentation-table"> + <tr> + <th colspan="1">Key</th> + <th>Returned</th> + <th width="100%">Description</th> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="return-"></div> + <b>commands</b> + <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a> + <div style="font-size: small"> + <span style="color: purple">list</span> + </div> + </td> + <td>when state is read</td> + <td> + <div>List of commands sent</div> + <br/> + <div style="font-size: smaller"><b>Sample:</b></div> + <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['/usr/local/bin/ovs-vsctl -t 5 get interface vhuclient1 statistics:tx_packets']</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="return-"></div> + <b>output</b> + <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a> + <div style="font-size: small"> + <span style="color: purple">dictionary</span> + </div> + </td> + <td>when state is read</td> + <td> + <div>Output of the commands</div> + <br/> + <div style="font-size: smaller"><b>Sample:</b></div> + <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{'tx_packets': '0'}</div> + </td> + </tr> + </table> + <br/><br/> + + +Status +------ + + +Authors +~~~~~~~ + +- Mark Hamilton (@markleehamilton) <mhamilton@vmware.com> diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst new file mode 100644 index 000000000..b5248a975 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst @@ -0,0 +1,236 @@ +.. _openvswitch.openvswitch.openvswitch_port_module: + + +**************************************** +openvswitch.openvswitch.openvswitch_port +**************************************** + +**Manage Open vSwitch ports** + + +Version added: 1.0.0 + +.. contents:: + :local: + :depth: 1 + + +Synopsis +-------- +- Manage Open vSwitch ports + + + +Requirements +------------ +The below requirements are needed on the host that executes this module. + +- ovs-vsctl + + +Parameters +---------- + +.. raw:: html + + <table border=0 cellpadding=0 class="documentation-table"> + <tr> + <th colspan="1">Parameter</th> + <th>Choices/<font color="blue">Defaults</font></th> + <th width="100%">Comments</th> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>bridge</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Name of bridge to manage</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>database_socket</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>Path/ip to datbase socket to use</div> + <div>Default path is used if not specified</div> + <div>Path should start with 'unix:' prefix</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>external_ids</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">dictionary</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">{}</div> + </td> + <td> + <div>Dictionary of external_ids applied to a port.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>port</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + / <span style="color: red">required</span> + </div> + </td> + <td> + </td> + <td> + <div>Name of port to manage on the bridge</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>set</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">list</span> + / <span style="color: purple">elements=string</span> + </div> + </td> + <td> + </td> + <td> + <div>Set multiple properties on a port.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>state</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + <ul style="margin: 0; padding: 0"><b>Choices:</b> + <li><div style="color: blue"><b>present</b> ←</div></li> + <li>absent</li> + </ul> + </td> + <td> + <div>Whether the port should exist</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>tag</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">string</span> + </div> + </td> + <td> + </td> + <td> + <div>VLAN tag for this port. Must be a value between 0 and 4095.</div> + </td> + </tr> + <tr> + <td colspan="1"> + <div class="ansibleOptionAnchor" id="parameter-"></div> + <b>timeout</b> + <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a> + <div style="font-size: small"> + <span style="color: purple">integer</span> + </div> + </td> + <td> + <b>Default:</b><br/><div style="color: blue">5</div> + </td> + <td> + <div>How long to wait for ovs-vswitchd to respond</div> + </td> + </tr> + </table> + <br/> + + + + +Examples +-------- + +.. code-block:: yaml + + # Creates port eth2 on bridge br-ex + - openvswitch.openvswitch.openvswitch_port: + bridge: br-ex + port: eth2 + state: present + + # Creates port eth6 + - openvswitch.openvswitch.openvswitch_port: + bridge: bridge-loop + port: eth6 + state: present + set: Interface eth6 + + # Creates port vlan10 with tag 10 on bridge br-ex + - openvswitch.openvswitch.openvswitch_port: + bridge: br-ex + port: vlan10 + tag: 10 + state: present + set: Interface vlan10 + + # Assign interface id server1-vifeth6 and mac address 00:00:5E:00:53:23 + # to port vifeth6 and setup port to be managed by a controller. + - openvswitch.openvswitch.openvswitch_port: + bridge: br-int + port: vifeth6 + state: present + args: + external_ids: + iface-id: '{{ inventory_hostname }}-vifeth6' + attached-mac: 00:00:5E:00:53:23 + vm-id: '{{ inventory_hostname }}' + iface-status: active + + # Plugs port veth0 into brdige br0 for database for OVSDB instance + # with socket unix:/opt/second_ovsdb.sock + - openvswitch.openvswitch.openvswitch_port: + bridge: br0 + port: veth0 + state: present + database_socket: unix:/opt/second_ovsdb.sock + + + + +Status +------ + + +Authors +~~~~~~~ + +- David Stygstra (@stygstra) diff --git a/ansible_collections/openvswitch/openvswitch/meta/runtime.yml b/ansible_collections/openvswitch/openvswitch/meta/runtime.yml new file mode 100644 index 000000000..c3911995d --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/meta/runtime.yml @@ -0,0 +1,12 @@ +--- +requires_ansible: ">=2.9.10" +plugin_routing: + modules: + bridge: + redirect: openvswitch.openvswitch.openvswitch_bridge + db: + redirect: openvswitch.openvswitch.openvswitch_db + port: + redirect: openvswitch.openvswitch.openvswitch_port + bond: + redirect: openvswitch.openvswitch.openvswitch_bond diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py new file mode 100644 index 000000000..ece20811f --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py @@ -0,0 +1,391 @@ +#!/usr/bin/python +# coding: utf-8 -*- + +# (c) 2020, James Denton <james.denton@outlook.com> +# Portions copyright @ 2013 David Stygstra <david.stygstra@gmail.com> +# Portions copyright @ 2015 VMware, Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = """ +--- +module: openvswitch_bond +author: "James Denton (@busterswt)" +short_description: Manage Open vSwitch bonds +requirements: +- ovs-vsctl +description: +- Manage Open vSwitch bonds and associated options. +version_added: '1.0.0' +options: + bridge: + required: true + description: + - Name of bridge to manage + type: str + port: + required: true + description: + - Name of port to manage on the bridge + type: str + interfaces: + description: + - List of interfaces to add to the bond + type: list + elements: str + bond_mode: + choices: [ active-backup, balance-tcp, balance-slb ] + description: + - Sets the bond mode + type: str + lacp: + choices: [ 'active', 'passive', 'off' ] + description: + - Sets LACP mode + type: str + bond_updelay: + description: + - Number of milliseconds a link must be up to be activated + to prevent flapping. + type: int + bond_downdelay: + description: + - Number of milliseconds a link must be down to be deactivated + to prevent flapping. + type: int + state: + default: 'present' + choices: [ 'present', 'absent' ] + description: + - Whether the port should exist + type: str + timeout: + default: 5 + description: + - How long to wait for ovs-vswitchd to respond in seconds + type: int + external_ids: + default: {} + description: + - Dictionary of external_ids applied to a port. + type: dict + other_config: + default: {} + description: + - Dictionary of other_config applied to a port. + type: dict + set: + description: + - Sets one or more properties on a port. + type: list + elements: str + database_socket: + description: + - Path/ip to datbase socket to use + - Default path is used if not specified + - Path should start with 'unix:' prefix + type: str +""" + +EXAMPLES = """ +- name: Create an active-backup bond using eth4 and eth5 on bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + state: present +- name: Delete the bond from bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + state: absent +- name: Create an active LACP bond using eth4 and eth5 on bridge br-ex + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + lacp: active + state: present +# NOTE: other_config values of integer type must be represented +# as literal strings +- name: Configure bond with miimon link monitoring at 100 millisecond intervals + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + bond_updelay: 100 + bond_downdelay: 100 + state: present + args: + other_config: + bond-detect-mode: miimon + bond-miimon-interval: '"100"' +- name: Create an active LACP bond using DPDK interfaces + openvswitch.openvswitch.openvswitch_bond: + bridge: br-provider + port: dpdkbond + interfaces: + - "0000:04:00.0" + - "0000:04:00.1" + lacp: active + set: + - "interface 0000:04:00.0 type=dpdk options:dpdk-devargs=0000:04:00.0" + - "interface 0000:04:00.1 type=dpdk options:dpdk-devargs=0000:04:00.1" + state: present +- name: Create an active-backup bond using eth4 and eth5 on bridge br-ex in second OVS database + openvswitch.openvswitch.openvswitch_bond: + bridge: br-ex + port: bond1 + interfaces: + - eth4 + - eth5 + state: present + database_socket: unix:/opt/second.sock +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.six import iteritems + + +def _external_ids_to_dict(text): + text = text.strip() + + if text == "{}": + return None + + else: + d = {} + + for kv in text[1:-1].split(","): + kv = kv.strip() + k, v = kv.split("=") + d[k] = v + + return d + + +def _other_config_to_dict(text): + text = text.strip() + + if text == "{}": + return None + else: + d = {} + + for kv in text[1:-1].split(","): + kv = kv.strip() + k, v = kv.split("=") + d[k] = v + + return d + + +def map_obj_to_commands(want, have, module): + commands = list() + + if module.params["state"] == "absent": + if have: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-port %(bridge)s %(port)s" + command = templatized_command % module.params + commands.append(command) + else: + if have: + if want["other_config"] != have["other_config"]: + for k, v in iteritems(want["other_config"]): + if ( + not have["other_config"] + or k not in have["other_config"] + or want["other_config"][k] != have["other_config"][k] + ): + if v is None: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s remove port %(port)s other_config " + + k + ) + command = templatized_command % module.params + commands.append(command) + else: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s other_config:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + + if want["external_ids"] != have["external_ids"]: + for k, v in iteritems(want["external_ids"]): + if ( + not have["external_ids"] + or k not in have["external_ids"] + or want["external_ids"][k] != have["external_ids"][k] + ): + if v is None: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s remove port %(port)s external_ids " + + k + ) + command = templatized_command % module.params + commands.append(command) + else: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + + else: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-bond %(bridge)s %(port)s" + command = templatized_command % module.params + + if want["interfaces"]: + for interface in want["interfaces"]: + command += " " + interface + + if want["bond_mode"]: + templatized_command = " bond_mode=%(bond_mode)s" + command += templatized_command % module.params + + if want["lacp"]: + templatized_command = " lacp=%(lacp)s" + command += templatized_command % module.params + + if want["bond_updelay"]: + templatized_command = " bond_updelay=%(bond_updelay)s" + command += templatized_command % module.params + + if want["bond_downdelay"]: + templatized_command = " bond_downdelay=%(bond_downdelay)s" + command += templatized_command % module.params + + if want["set"]: + for set in want["set"]: + command += " -- set " + set + + commands.append(command) + + if want["other_config"]: + for k, v in iteritems(want["other_config"]): + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s other_config:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + + if want["external_ids"]: + for k, v in iteritems(want["external_ids"]): + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + + return commands + + +def map_config_to_obj(module): + templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-ports %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + if rc != 0: + module.fail_json(msg=err) + + obj = {} + + if module.params["port"] in out.splitlines(): + obj["bridge"] = module.params["bridge"] + obj["port"] = module.params["port"] + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s other_config" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["other_config"] = _other_config_to_dict(out) + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s external_ids" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["external_ids"] = _external_ids_to_dict(out) + + return obj + + +def map_params_to_obj(module): + obj = { + "bridge": module.params["bridge"], + "port": module.params["port"], + "interfaces": module.params["interfaces"], + "bond_mode": module.params["bond_mode"], + "lacp": module.params["lacp"], + "bond_updelay": module.params["bond_updelay"], + "bond_downdelay": module.params["bond_downdelay"], + "external_ids": module.params["external_ids"], + "other_config": module.params["other_config"], + "set": module.params["set"], + } + + return obj + + +def main(): + """Entry point.""" + argument_spec = { + "bridge": {"required": True}, + "port": {"required": True}, + "interfaces": {"type": "list", "elements": "str"}, + "bond_mode": { + "default": None, + "choices": ["active-backup", "balance-tcp", "balance-slb"], + }, + "lacp": {"default": None, "choices": ["active", "passive", "off"]}, + "bond_updelay": {"default": None, "type": "int"}, + "bond_downdelay": {"default": None, "type": "int"}, + "state": {"default": "present", "choices": ["present", "absent"]}, + "timeout": {"default": 5, "type": "int"}, + "external_ids": {"default": {}, "type": "dict"}, + "other_config": {"default": {}, "type": "dict"}, + "set": { + "required": False, + "type": "list", + "default": None, + "elements": "str", + }, + "database_socket": {"default": None}, + } + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + result = {"changed": False} + + # We add ovs-vsctl to module_params to later build up templatized commands + module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True) + if module.params.get("database_socket"): + module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket") + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands(want, have, module) + result["commands"] = commands + + if commands: + if not module.check_mode: + for c in commands: + module.run_command(c, check_rc=True) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py new file mode 100644 index 000000000..0aed44d79 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py @@ -0,0 +1,286 @@ +#!/usr/bin/python + +# (c) 2013, David Stygstra <david.stygstra@gmail.com> +# Portions copyright @ 2015 VMware, Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +DOCUMENTATION = """ +module: openvswitch_bridge +author: David Stygstra (@stygstra) +short_description: Manage Open vSwitch bridges +requirements: +- ovs-vsctl +description: +- Manage Open vSwitch bridges +version_added: 1.0.0 +options: + bridge: + required: true + description: + - Name of bridge or fake bridge to manage + type: str + parent: + description: + - Bridge parent of the fake bridge to manage + type: str + vlan: + description: + - The VLAN id of the fake bridge to manage (must be between 0 and 4095). This + parameter is required if I(parent) parameter is set. + type: int + state: + default: present + choices: + - present + - absent + description: + - Whether the bridge should exist + type: str + timeout: + default: 5 + description: + - How long to wait for ovs-vswitchd to respond + type: int + external_ids: + description: + - A dictionary of external-ids. Omitting this parameter is a No-op. To clear + all external-ids pass an empty value. + type: dict + fail_mode: + description: + - Set bridge fail-mode. The default value (None) is a No-op. + type: str + set: + description: + - Run set command after bridge configuration. This parameter is non-idempotent, + play will always return I(changed) state if present + type: str + database_socket: + description: + - Path/ip to datbase socket to use + - Default path is used if not specified + - Path should start with 'unix:' prefix + type: str +""" + +EXAMPLES = """ +# Create a bridge named br-int +- openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + state: present + +# Create a fake bridge named br-int within br-parent on the VLAN 405 +- openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + parent: br-parent + vlan: 405 + state: present + +# Create an integration bridge +- openvswitch.openvswitch.openvswitch_bridge: + bridge: br-int + state: present + fail_mode: secure + args: + external_ids: + bridge-id: br-int +# Create a bridge named br0 in database with socket at /opt/second.sock +- openvswitch.openvswitch.openvswitch_bridge: + bridge: br0 + state: present + database_socket: unix:/opt/second.sock +""" + +from ansible.module_utils._text import to_text +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.six import iteritems + + +def _fail_mode_to_str(text): + if not text: + return None + else: + return text.strip() + + +def _external_ids_to_dict(text): + if not text: + return None + else: + d = {} + + for l in text.splitlines(): + if l: + k, v = l.split("=") + d[k] = v + + return d + + +def map_obj_to_commands(want, have, module): + commands = list() + + if module.params["state"] == "absent": + if have: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-br %(bridge)s" + command = templatized_command % module.params + commands.append(command) + else: + if have: + if want["fail_mode"] != have["fail_mode"]: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set-fail-mode %(bridge)s %(fail_mode)s" + ) + command = templatized_command % module.params + commands.append(command) + + if want["external_ids"] != have["external_ids"]: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-set-external-id %(bridge)s" + command = templatized_command % module.params + if want["external_ids"]: + for k, v in iteritems(want["external_ids"]): + if ( + k not in have["external_ids"] + or want["external_ids"][k] != have["external_ids"][k] + ): + command += " " + k + " " + v + commands.append(command) + + if want["vlan"] and to_text(want["vlan"]) != have["vlan"]: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(bridge)s tag=%(vlan)s" + ) + command = templatized_command % module.params + commands.append(command) + else: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-br %(bridge)s" + command = templatized_command % module.params + + if want["parent"]: + templatized_command = "%(parent)s %(vlan)s" + command += " " + templatized_command % module.params + + if want["set"]: + templatized_command = " -- set %(set)s" + command += templatized_command % module.params + + commands.append(command) + + if want["fail_mode"]: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set-fail-mode %(bridge)s %(fail_mode)s" + ) + command = templatized_command % module.params + commands.append(command) + + if want["external_ids"]: + for k, v in iteritems(want["external_ids"]): + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s br-set-external-id %(bridge)s" + ) + command = templatized_command % module.params + command += " " + k + " " + v + commands.append(command) + + return commands + + +def map_config_to_obj(module): + templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-br" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + if rc != 0: + module.fail_json(msg=err) + + obj = {} + + if module.params["bridge"] in out.splitlines(): + obj["bridge"] = module.params["bridge"] + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-to-parent %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["parent"] = out.strip() + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-to-vlan %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["vlan"] = out.strip() + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get-fail-mode %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["fail_mode"] = _fail_mode_to_str(out) + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-get-external-id %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["external_ids"] = _external_ids_to_dict(out) + + return obj + + +def map_params_to_obj(module): + obj = { + "bridge": module.params["bridge"], + "parent": module.params["parent"], + "vlan": module.params["vlan"], + "fail_mode": module.params["fail_mode"], + "external_ids": module.params["external_ids"], + "set": module.params["set"], + } + + return obj + + +def main(): + """Entry point.""" + argument_spec = { + "bridge": {"required": True}, + "parent": {"default": None}, + "vlan": {"default": None, "type": "int"}, + "state": {"default": "present", "choices": ["present", "absent"]}, + "timeout": {"default": 5, "type": "int"}, + "external_ids": {"default": None, "type": "dict"}, + "fail_mode": {"default": None}, + "set": {"required": False, "default": None}, + "database_socket": {"default": None}, + } + + required_if = [("parent", not None, ("vlan",))] + + module = AnsibleModule( + argument_spec=argument_spec, + required_if=required_if, + supports_check_mode=True, + ) + + result = {"changed": False} + + # We add ovs-vsctl to module_params to later build up templatized commands + module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True) + if module.params.get("database_socket"): + module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket") + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands(want, have, module) + result["commands"] = commands + + if commands: + if not module.check_mode: + for c in commands: + module.run_command(c, check_rc=True) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py new file mode 100644 index 000000000..b4928704a --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py @@ -0,0 +1,314 @@ +#!/usr/bin/python + +# +# (c) 2015, Mark Hamilton <mhamilton@vmware.com> +# Portions copyright @ 2015 VMware, Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +DOCUMENTATION = """ +module: openvswitch_db +author: Mark Hamilton (@markleehamilton) <mhamilton@vmware.com> +short_description: Configure open vswitch database. +requirements: +- ovs-vsctl >= 2.3.3 +description: +- Set column values in record in database table. +version_added: 1.0.0 +options: + state: + required: false + description: + - Configures the state of the key. When set to I(present), the I(key) and I(value) + pair will be set on the I(record) and when set to I(absent) the I(key) will + not be set. + default: present + choices: + - present + - absent + - read + type: str + table: + required: true + description: + - Identifies the table in the database. + type: str + record: + required: true + description: + - Identifies the record in the table. + type: str + col: + required: true + description: + - Identifies the column in the record. + type: str + key: + required: false + description: + - Identifies the key in the record column, when the column is a map type. + type: str + value: + description: + - Expected value for the table, record, column and key. + type: str + timeout: + required: false + default: 5 + description: + - How long to wait for ovs-vswitchd to respond + type: int + database_socket: + description: + - Path/ip to datbase socket to use + - Default path is used if not specified + - Path should start with 'unix:' prefix + type: str +""" + +EXAMPLES = """ +# Increase the maximum idle time to 50 seconds before pruning unused kernel +# rules. +- openvswitch.openvswitch.openvswitch_db: + table: open_vswitch + record: . + col: other_config + key: max-idle + value: 50000 + +# Disable in band copy +- openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-int + col: other_config + key: disable-in-band + value: true + +# Remove in band key +- openvswitch.openvswitch.openvswitch_db: + state: present + table: Bridge + record: br-int + col: other_config + key: disable-in-band + +# Mark port with tag 10 +- openvswitch.openvswitch.openvswitch_db: + table: Port + record: port0 + col: tag + value: 10 + +# Mark port with tag 10 for OVSDB with socket in /opt/second.sock +- openvswitch.openvswitch.openvswitch_db: + table: Port + record: port0 + col: tag + value: 10 + database_socket: unix:/opt/second.sock + +# Get interface statistics +- openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: statistics + +# Get tx_packets value +- openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: statistics + key: tx_packets + +# Get mtu value +- openvswitch.openvswitch.openvswitch_db: + state: read + table: interface + record: ifname + col: mtu +""" + +RETURN = """ +commands: + description: List of commands sent + returned: when state is read + type: list + sample: ["/usr/local/bin/ovs-vsctl -t 5 get interface vhuclient1 statistics:tx_packets"] +output: + description: Output of the commands + returned: when state is read + type: dict + sample: {"tx_packets": "0"} +""" +import re + +from ansible.module_utils.basic import AnsibleModule + +# Regular expression for map type, must not be empty +NON_EMPTY_MAP_RE = re.compile(r"{.+}") +# Regular expression for a map column type +MAP_RE = re.compile(r"{.*}") + + +def map_obj_to_commands(want, have, module): + """Define ovs-vsctl command to meet desired state""" + commands = list() + + if module.params["state"] == "absent": + if "key" in have.keys(): + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s remove %(table)s %(record)s %(col)s %(key)s" + ) + if module.params.get("value"): + templatized_command += "=%(value)s" + commands.append(templatized_command % module.params) + elif module.params["key"] is None: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s remove %(table)s %(record)s %(col)s" + commands.append(templatized_command % module.params) + elif module.params["state"] == "read": + if module.params["key"] is None: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get %(table)s %(record)s %(col)s" + commands.append(templatized_command % module.params) + else: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s get %(table)s %(record)s %(col)s:%(key)s" + ) + commands.append(templatized_command % module.params) + else: + if want == have: + # Nothing to commit + return commands + if module.params["key"] is None: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set %(table)s %(record)s %(col)s=%(value)s" + ) + commands.append(templatized_command % module.params) + else: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set %(table)s %(record)s %(col)s:%(key)s=%(value)s" + ) + commands.append(templatized_command % module.params) + + return commands + + +def map_config_to_obj(module): + templatized_command = "%(ovs-vsctl)s -t %(timeout)s list %(table)s %(record)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + if rc != 0: + module.fail_json(msg=err) + + match = re.search(r"^" + module.params["col"] + r"(\s+):(\s+)(.*)$", out, re.M) + + col_value = match.group(3) + + # Map types require key argument + has_key = module.params["key"] is not None + is_map = MAP_RE.match(col_value) + if is_map and not has_key and module.params["state"] != "read": + module.fail_json(msg="missing required arguments: key for map type of column") + + col_value_to_dict = {} + if NON_EMPTY_MAP_RE.match(col_value): + for kv in col_value[1:-1].split(", "): + k, v = kv.split("=", 1) + col_value_to_dict[k.strip()] = v.strip('"') + + obj = { + "table": module.params["table"], + "record": module.params["record"], + "col": module.params["col"], + } + + if has_key and is_map: + if module.params["key"] in col_value_to_dict: + obj["key"] = module.params["key"] + obj["value"] = col_value_to_dict[module.params["key"]] + else: + obj["value"] = str(col_value.strip()) + + return obj + + +def map_params_to_obj(module): + if module.params["value"] in ["True", "False"]: + module.params["value"] = module.params["value"].lower() + obj = { + "table": module.params["table"], + "record": module.params["record"], + "col": module.params["col"], + "value": module.params["value"], + } + + key = module.params["key"] + if key is not None: + obj["key"] = key + + return obj + + +def main(): + """Entry point for ansible module.""" + argument_spec = { + "state": { + "default": "present", + "choices": ["present", "absent", "read"], + }, + "table": {"required": True}, + "record": {"required": True}, + "col": {"required": True}, + "key": {"required": False, "no_log": False}, + "value": {"type": "str"}, + "timeout": {"default": 5, "type": "int"}, + "database_socket": {"default": None}, + } + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + result = {"changed": False} + + # We add ovs-vsctl to module_params to later build up templatized commands + module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True) + if module.params.get("database_socket"): + module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket") + + if module.params["state"] == "present" and not module.params["value"]: + module.fail_json(msg="missing required argument value for state: present") + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands(want, have, module) + result["commands"] = commands + + if commands: + if not module.check_mode: + for c in commands: + rc, out, err = module.run_command(c, check_rc=True) + result["changed"] = True + + string_to_dict = {} + + if NON_EMPTY_MAP_RE.match(str(out)): + for kv in re.split(r", ", out[1:-1]): + k, v = re.split(r"=", kv, 1) + string_to_dict[re.search("\\w*", k).group(0)] = re.search("\\d*", v).group(0) + else: + if module.params["key"] is not None: + string_to_dict[module.params["key"]] = re.search("\\w*", str(out)).group(0) + else: + string_to_dict[module.params["col"]] = re.search("\\w*", str(out)).group(0) + result["output"] = string_to_dict + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py new file mode 100644 index 000000000..ba1f9daa2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py @@ -0,0 +1,282 @@ +#!/usr/bin/python + +# (c) 2013, David Stygstra <david.stygstra@gmail.com> +# Portions copyright @ 2015 VMware, Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +DOCUMENTATION = """ +module: openvswitch_port +author: David Stygstra (@stygstra) +short_description: Manage Open vSwitch ports +requirements: +- ovs-vsctl +description: +- Manage Open vSwitch ports +version_added: 1.0.0 +options: + bridge: + required: true + description: + - Name of bridge to manage + type: str + port: + required: true + description: + - Name of port to manage on the bridge + type: str + tag: + description: + - VLAN tag for this port. Must be a value between 0 and 4095. + type: str + state: + default: present + choices: + - present + - absent + description: + - Whether the port should exist + type: str + timeout: + default: 5 + description: + - How long to wait for ovs-vswitchd to respond + type: int + external_ids: + default: {} + description: + - Dictionary of external_ids applied to a port. + type: dict + set: + description: + - Set multiple properties on a port. + type: list + elements: str + database_socket: + description: + - Path/ip to datbase socket to use + - Default path is used if not specified + - Path should start with 'unix:' prefix + type: str +""" + +EXAMPLES = """ +# Creates port eth2 on bridge br-ex +- openvswitch.openvswitch.openvswitch_port: + bridge: br-ex + port: eth2 + state: present + +# Creates port eth6 +- openvswitch.openvswitch.openvswitch_port: + bridge: bridge-loop + port: eth6 + state: present + set: Interface eth6 + +# Creates port vlan10 with tag 10 on bridge br-ex +- openvswitch.openvswitch.openvswitch_port: + bridge: br-ex + port: vlan10 + tag: 10 + state: present + set: Interface vlan10 + +# Assign interface id server1-vifeth6 and mac address 00:00:5E:00:53:23 +# to port vifeth6 and setup port to be managed by a controller. +- openvswitch.openvswitch.openvswitch_port: + bridge: br-int + port: vifeth6 + state: present + args: + external_ids: + iface-id: '{{ inventory_hostname }}-vifeth6' + attached-mac: 00:00:5E:00:53:23 + vm-id: '{{ inventory_hostname }}' + iface-status: active + +# Plugs port veth0 into brdige br0 for database for OVSDB instance +# with socket unix:/opt/second_ovsdb.sock +- openvswitch.openvswitch.openvswitch_port: + bridge: br0 + port: veth0 + state: present + database_socket: unix:/opt/second_ovsdb.sock + +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.six import iteritems + + +def _external_ids_to_dict(text): + text = text.strip() + + if text == "{}": + return None + else: + d = {} + + for kv in text[1:-1].split(","): + kv = kv.strip() + k, v = kv.split("=") + d[k] = v + + return d + + +def _tag_to_str(text): + text = text.strip() + + if text == "[]": + return None + else: + return text + + +def map_obj_to_commands(want, have, module): + commands = list() + + if module.params["state"] == "absent": + if have: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-port %(bridge)s %(port)s" + command = templatized_command % module.params + commands.append(command) + else: + if have: + if want["tag"] != have["tag"]: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s set port %(port)s tag=%(tag)s" + command = templatized_command % module.params + commands.append(command) + + if want["external_ids"] != have["external_ids"]: + for k, v in iteritems(want["external_ids"]): + if ( + not have["external_ids"] + or k not in have["external_ids"] + or want["external_ids"][k] != have["external_ids"][k] + ): + if v is None: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s" + " remove port %(port)s" + " external_ids " + k + ) + command = templatized_command % module.params + commands.append(command) + else: + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + else: + templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-port %(bridge)s %(port)s" + command = templatized_command % module.params + + if want["tag"]: + templatized_command = " tag=%(tag)s" + command += templatized_command % module.params + + if want["set"]: + set_command = "" + for x in want["set"]: + set_command += " -- set {0}".format(x) + command += set_command + + commands.append(command) + + if want["external_ids"]: + for k, v in iteritems(want["external_ids"]): + templatized_command = ( + "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:" + ) + command = templatized_command % module.params + command += k + "=" + v + commands.append(command) + + return commands + + +def map_config_to_obj(module): + templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-ports %(bridge)s" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + if rc != 0: + module.fail_json(msg=err) + + obj = {} + + if module.params["port"] in out.splitlines(): + obj["bridge"] = module.params["bridge"] + obj["port"] = module.params["port"] + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s tag" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["tag"] = _tag_to_str(out) + + templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s external_ids" + command = templatized_command % module.params + rc, out, err = module.run_command(command, check_rc=True) + obj["external_ids"] = _external_ids_to_dict(out) + + return obj + + +def map_params_to_obj(module): + obj = { + "bridge": module.params["bridge"], + "port": module.params["port"], + "tag": module.params["tag"], + "external_ids": module.params["external_ids"], + "set": module.params["set"], + } + + return obj + + +def main(): + """Entry point.""" + argument_spec = { + "bridge": {"required": True}, + "port": {"required": True}, + "state": {"default": "present", "choices": ["present", "absent"]}, + "timeout": {"default": 5, "type": "int"}, + "external_ids": {"default": {}, "type": "dict"}, + "tag": {"default": None}, + "database_socket": {"default": None}, + "set": {"required": False, "type": "list", "elements": "str"}, + } + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + result = {"changed": False} + + # We add ovs-vsctl to module_params to later build up templatized commands + module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True) + if module.params.get("database_socket"): + module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket") + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands(want, have, module) + result["commands"] = commands + + if commands: + if not module.check_mode: + for c in commands: + module.run_command(c, check_rc=True) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/ansible_collections/openvswitch/openvswitch/pyproject.toml b/ansible_collections/openvswitch/openvswitch/pyproject.toml new file mode 100644 index 000000000..fa4225f3e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/pyproject.toml @@ -0,0 +1,7 @@ +[tool.black] +line-length = 100 + +[tool.pytest.ini_options] +addopts = ["-vvv", "-n", "2", "--log-level", "WARNING", "--color", "yes"] +testpaths = ["tests"] +filterwarnings = ['ignore:AnsibleCollectionFinder has already been configured'] diff --git a/ansible_collections/openvswitch/openvswitch/requirements.txt b/ansible_collections/openvswitch/openvswitch/requirements.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/requirements.txt diff --git a/ansible_collections/openvswitch/openvswitch/test-requirements.txt b/ansible_collections/openvswitch/openvswitch/test-requirements.txt new file mode 100644 index 000000000..2a8e6fb7e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/test-requirements.txt @@ -0,0 +1,7 @@ +black==22.3.0 ; python_version > '3.5' +coverage==4.5.4 +flake8 +git+https://github.com/ansible-community/pytest-ansible-units.git +mock ; python_version < '3.5' +pytest-xdist +yamllint diff --git a/ansible_collections/openvswitch/openvswitch/tests/.gitignore b/ansible_collections/openvswitch/openvswitch/tests/.gitignore new file mode 100644 index 000000000..ea1472ec1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg b/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg new file mode 100644 index 000000000..d12c1efe2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg @@ -0,0 +1,4 @@ +[persistent_connection] +command_timeout = 100 +connect_timeout = 100 +connect_retry_timeout = 100 diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network b/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network new file mode 100644 index 000000000..64796f72c --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network @@ -0,0 +1 @@ +openvswitch diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases new file mode 100644 index 000000000..a51f9c505 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases @@ -0,0 +1 @@ +non_local diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml new file mode 100644 index 000000000..9ef5ba516 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml new file mode 100644 index 000000000..846a02ba2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_ovs_tests diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml new file mode 100644 index 000000000..3eaedab1e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: collect all test cases + find: + paths: "{{ role_path }}/tests" + patterns: "{{ testcase }}.yaml" + delegate_to: localhost + register: test_cases + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test case + include: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml new file mode 100644 index 000000000..6ea2a2f3e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml @@ -0,0 +1,65 @@ +--- +- name: Make sure test bridge does not exist before tests + command: ovs-vsctl del-br br-test + become: true + ignore_errors: true + +- name: Create bridge + register: result + become: true + openvswitch.openvswitch.openvswitch_bridge: + bridge: br-test + +- assert: + that: + - result is changed + +- name: Create bridge again (idempotent) + register: result + become: true + openvswitch.openvswitch.openvswitch_bridge: + bridge: br-test + +- assert: + that: + - result is not changed + +- name: Add fake bridge + register: result + become: true + openvswitch.openvswitch.openvswitch_bridge: + bridge: fake-br-test + parent: br-test + vlan: 100 + +- assert: + that: + - result is changed + +- name: Change fake bridge vlan + register: result + become: true + openvswitch.openvswitch.openvswitch_bridge: + bridge: fake-br-test + parent: br-test + vlan: 300 + +- assert: + that: + - result is changed + +- name: Change fake bridge vlan again (idempotent) + register: result + become: true + openvswitch.openvswitch.openvswitch_bridge: + bridge: fake-br-test + parent: br-test + vlan: 300 + +- assert: + that: + - result is not changed + +- name: Tear down test bridges + become: true + command: ovs-vsctl del-br br-test diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases new file mode 100644 index 000000000..a51f9c505 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases @@ -0,0 +1 @@ +non_local diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml new file mode 100644 index 000000000..9ef5ba516 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +testcase: "*" +test_items: [] diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml new file mode 100644 index 000000000..846a02ba2 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - prepare_ovs_tests diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml new file mode 100644 index 000000000..3eaedab1e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: collect all test cases + find: + paths: "{{ role_path }}/tests" + patterns: "{{ testcase }}.yaml" + delegate_to: localhost + register: test_cases + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test case + include: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml new file mode 100644 index 000000000..b20413565 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml @@ -0,0 +1,182 @@ +--- +- name: Make sure test bridge does not exist before tests + command: ovs-vsctl del-br br-test + become: true + ignore_errors: true + +- name: Create test bridge + command: ovs-vsctl add-br br-test + become: true + +- name: Create bridge + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: true + +- assert: + that: + - result is changed + +- name: Create bridge again (idempotent) + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: true + +- assert: + that: + - result is not changed + +- name: Change key value with quotes + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: open_vswitch + record: . + col: other_config + key: pmd-cpu-mask + value: "0xaaa00000000" + +- assert: + that: + - result is changed + +- name: Change keyvalue with quotes(idempotent) + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: open_vswitch + record: . + col: other_config + key: pmd-cpu-mask + value: "0xaaa00000000" + +- assert: + that: + - result is not changed + +- name: Remove key value with quotes + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: open_vswitch + record: . + col: other_config + key: pmd-cpu-mask + value: "0xaaa00000000" + state: absent + +- assert: + that: + - result is changed + +- name: Change column value in a map + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: false + +- assert: + that: + - result is changed + +- name: Change column value in a map again (idempotent) + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: false + +- assert: + that: + - result is not changed + +- name: Change column value + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: stp_enable + value: true + +- assert: + that: + - result is changed + +- name: Change column value again (idempotent) + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: stp_enable + value: true + +- assert: + that: + - result is not changed + +- name: Try to set value on a map type without a key (negative) + ignore_errors: true + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + value: true + +- assert: + that: + - result is failed + +- name: Remove bridge + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: false + state: absent + +- assert: + that: + - result is changed + +- name: Remove bridge again (idempotent) + become: true + register: result + openvswitch.openvswitch.openvswitch_db: + table: Bridge + record: br-test + col: other_config + key: disable-in-band + value: false + state: absent + +- assert: + that: + - result is not changed + +- name: Tear down test bridge + command: ovs-vsctl del-br br-test + become: true diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml new file mode 100644 index 000000000..924dbd3a4 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml @@ -0,0 +1,37 @@ +--- +# No easy way to know OS type without python or without ansible facts. +# Run below raw commands and one would succeed with apt/yum on debian/centos +- block: + - name: Install python + raw: test -e /usr/bin/python || (apt-get -y update && apt-get install -y python-minimal) + become: yes + ignore_errors: yes + + - name: Install python + raw: test -e /usr/bin/python || (yum -y update && yum install -y python) + become: yes + ignore_errors: yes + + # network-integration test are ran with gather_facts: no + # We need to explicitly call setup so ansible_distribution is set + + - name: Gather facts + setup: + become: yes + + - name: Install openvswitch-switch package if we are on Ubuntu + apt: + name: openvswitch-switch + state: present + update_cache: yes + become: yes + when: ansible_distribution == 'Ubuntu' + + - name: Install openvswitch package if we are on Fedora + yum: + name: openvswitch + state: installed + update_cache: yes + become: yes + when: ansible_distribution == 'Fedora' + when: prepare_ovs_tests_task | default(False) | bool diff --git a/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt diff --git a/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py new file mode 100644 index 000000000..54c1d20e7 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py @@ -0,0 +1,125 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +""" +Compat module for Python3.x's unittest.mock module +""" +import sys + +# Python 2.7 + +# Note: Could use the pypi mock library on python3.x as well as python2.x. It +# is the same as the python3 stdlib mock library + +try: + # Allow wildcard import because we really do want to import all of mock's + # symbols into this compat shim + # pylint: disable=wildcard-import,unused-wildcard-import + from unittest.mock import * +except ImportError: + # Python 2 + # pylint: disable=wildcard-import,unused-wildcard-import + try: + from mock import * + except ImportError: + print("You need the mock library installed on python2.x to run tests") + + +# Prior to 3.4.4, mock_open cannot handle binary read_data +if sys.version_info >= (3,) and sys.version_info < (3, 4, 4): + file_spec = None + + def _iterate_read_data(read_data): + # Helper for mock_open: + # Retrieve lines from read_data via a generator so that separate calls to + # readline, read, and readlines are properly interleaved + sep = b"\n" if isinstance(read_data, bytes) else "\n" + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: + # If the last line ended in a newline, the list comprehension will have an + # extra entry that's just a newline. Remove this. + data_as_list = data_as_list[:-1] + else: + # If there wasn't an extra newline by itself, then the file being + # emulated doesn't have a newline to end the last line remove the + # newline that our naive format() added + data_as_list[-1] = data_as_list[-1][:-1] + + for line in data_as_list: + yield line + + def mock_open(mock=None, read_data=""): + """ + A helper function to create a mock to replace the use of `open`. It works + for `open` called directly or used as a context manager. + + The `mock` argument is the mock object to configure. If `None` (the + default) then a `MagicMock` will be created for you, with the API limited + to methods or attributes available on standard file handles. + + `read_data` is a string for the `read` methoddline`, and `readlines` of the + file handle to return. This is an empty string by default. + """ + + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return type(read_data)().join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + global file_spec + if file_spec is None: + import _io + + file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) + + if mock is None: + mock = MagicMock(name="open", spec=open) + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + + mock.return_value = handle + return mock diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py new file mode 100644 index 000000000..df3379b82 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py @@ -0,0 +1,39 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +""" +Compat module for Python2.7's unittest module +""" + +import sys + +# Allow wildcard import because we really do want to import all of +# unittests's symbols into this compat shim +# pylint: disable=wildcard-import,unused-wildcard-import +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + from unittest2 import * + except ImportError: + print("You need unittest2 installed on python2.6.x to run tests") +else: + from unittest import * diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py new file mode 100644 index 000000000..c141e66e5 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py @@ -0,0 +1,116 @@ +# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import os + +from ansible.errors import AnsibleParserError +from ansible.module_utils._text import to_bytes, to_text +from ansible.parsing.dataloader import DataLoader + + +class DictDataLoader(DataLoader): + def __init__(self, file_mapping=None): + file_mapping = {} if file_mapping is None else file_mapping + assert type(file_mapping) == dict + + super(DictDataLoader, self).__init__() + + self._file_mapping = file_mapping + self._build_known_directories() + self._vault_secrets = None + + def load_from_file(self, path, cache=True, unsafe=False): + path = to_text(path) + if path in self._file_mapping: + return self.load(self._file_mapping[path], path) + return None + + # TODO: the real _get_file_contents returns a bytestring, so we actually convert the + # unicode/text it's created with to utf-8 + def _get_file_contents(self, file_name): + file_name = to_text(file_name) + if file_name in self._file_mapping: + return (to_bytes(self._file_mapping[file_name]), False) + else: + raise AnsibleParserError("file not found: %s" % file_name) + + def path_exists(self, path): + path = to_text(path) + return path in self._file_mapping or path in self._known_directories + + def is_file(self, path): + path = to_text(path) + return path in self._file_mapping + + def is_directory(self, path): + path = to_text(path) + return path in self._known_directories + + def list_directory(self, path): + ret = [] + path = to_text(path) + for x in list(self._file_mapping.keys()) + self._known_directories: + if x.startswith(path): + if os.path.dirname(x) == path: + ret.append(os.path.basename(x)) + return ret + + def is_executable(self, path): + # FIXME: figure out a way to make paths return true for this + return False + + def _add_known_directory(self, directory): + if directory not in self._known_directories: + self._known_directories.append(directory) + + def _build_known_directories(self): + self._known_directories = [] + for path in self._file_mapping: + dirname = os.path.dirname(path) + while dirname not in ("/", ""): + self._add_known_directory(dirname) + dirname = os.path.dirname(dirname) + + def push(self, path, content): + rebuild_dirs = False + if path not in self._file_mapping: + rebuild_dirs = True + + self._file_mapping[path] = content + + if rebuild_dirs: + self._build_known_directories() + + def pop(self, path): + if path in self._file_mapping: + del self._file_mapping[path] + self._build_known_directories() + + def clear(self): + self._file_mapping = dict() + self._known_directories = [] + + def get_basedir(self): + return os.getcwd() + + def set_vault_secrets(self, vault_secrets): + self._vault_secrets = vault_secrets diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py new file mode 100644 index 000000000..2bc9ddea0 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py @@ -0,0 +1,9 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible.utils.path import unfrackpath + +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock + +mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py new file mode 100644 index 000000000..f3f0e3935 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py @@ -0,0 +1,95 @@ +# (c) 2016, Matt Davis <mdavis@ansible.com> +# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import json +import sys +from contextlib import contextmanager +from io import BytesIO, StringIO + +from ansible.module_utils._text import to_bytes +from ansible.module_utils.six import PY3 + +from ansible_collections.openvswitch.openvswitch.tests.unit.compat import unittest + + +@contextmanager +def swap_stdin_and_argv(stdin_data="", argv_data=tuple()): + """ + context manager that temporarily masks the test runner's values for stdin and argv + """ + real_stdin = sys.stdin + real_argv = sys.argv + + if PY3: + fake_stream = StringIO(stdin_data) + fake_stream.buffer = BytesIO(to_bytes(stdin_data)) + else: + fake_stream = BytesIO(to_bytes(stdin_data)) + + try: + sys.stdin = fake_stream + sys.argv = argv_data + + yield + finally: + sys.stdin = real_stdin + sys.argv = real_argv + + +@contextmanager +def swap_stdout(): + """ + context manager that temporarily replaces stdout for tests that need to verify output + """ + old_stdout = sys.stdout + + if PY3: + fake_stream = StringIO() + else: + fake_stream = BytesIO() + + try: + sys.stdout = fake_stream + + yield fake_stream + finally: + sys.stdout = old_stdout + + +class ModuleTestCase(unittest.TestCase): + def setUp(self, module_args=None): + if module_args is None: + module_args = { + "_ansible_remote_tmp": "/tmp", + "_ansible_keep_remote_files": False, + } + + args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args)) + + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap = swap_stdin_and_argv(stdin_data=args) + self.stdin_swap.__enter__() + + def tearDown(self): + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap.__exit__(None, None, None) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py new file mode 100644 index 000000000..4c6c890c1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py @@ -0,0 +1,39 @@ +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible.module_utils._text import to_bytes +from ansible.parsing.vault import VaultSecret + + +class TextVaultSecret(VaultSecret): + """A secret piece of text. ie, a password. Tracks text encoding. + + The text encoding of the text may not be the default text encoding so + we keep track of the encoding so we encode it to the same bytes.""" + + def __init__(self, text, encoding=None, errors=None, _bytes=None): + super(TextVaultSecret, self).__init__() + self.text = text + self.encoding = encoding or "utf-8" + self._bytes = _bytes + self.errors = errors or "strict" + + @property + def bytes(self): + """The text encoded with encoding, unless we specifically set _bytes.""" + return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py new file mode 100644 index 000000000..c5b29fcaf --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py @@ -0,0 +1,152 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import io + +import yaml +from ansible.module_utils.six import PY3 +from ansible.parsing.yaml.dumper import AnsibleDumper +from ansible.parsing.yaml.loader import AnsibleLoader + + +class YamlTestUtils(object): + """Mixin class to combine with a unittest.TestCase subclass.""" + + def _loader(self, stream): + """Vault related tests will want to override this. + + Vault cases should setup a AnsibleLoader that has the vault password.""" + return AnsibleLoader(stream) + + def _dump_stream(self, obj, stream, dumper=None): + """Dump to a py2-unicode or py3-string stream.""" + if PY3: + return yaml.dump(obj, stream, Dumper=dumper) + else: + return yaml.dump(obj, stream, Dumper=dumper, encoding=None) + + def _dump_string(self, obj, dumper=None): + """Dump to a py2-unicode or py3-string""" + if PY3: + return yaml.dump(obj, Dumper=dumper) + else: + return yaml.dump(obj, Dumper=dumper, encoding=None) + + def _dump_load_cycle(self, obj): + # Each pass though a dump or load revs the 'generation' + # obj to yaml string + string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper) + + # wrap a stream/file like StringIO around that yaml + stream_from_object_dump = io.StringIO(string_from_object_dump) + loader = self._loader(stream_from_object_dump) + # load the yaml stream to create a new instance of the object (gen 2) + obj_2 = loader.get_data() + + # dump the gen 2 objects directory to strings + string_from_object_dump_2 = self._dump_string(obj_2, dumper=AnsibleDumper) + + # The gen 1 and gen 2 yaml strings + self.assertEqual(string_from_object_dump, string_from_object_dump_2) + # the gen 1 (orig) and gen 2 py object + self.assertEqual(obj, obj_2) + + # again! gen 3... load strings into py objects + stream_3 = io.StringIO(string_from_object_dump_2) + loader_3 = self._loader(stream_3) + obj_3 = loader_3.get_data() + + string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper) + + self.assertEqual(obj, obj_3) + # should be transitive, but... + self.assertEqual(obj_2, obj_3) + self.assertEqual(string_from_object_dump, string_from_object_dump_3) + + def _old_dump_load_cycle(self, obj): + """Dump the passed in object to yaml, load it back up, dump again, compare.""" + stream = io.StringIO() + + yaml_string = self._dump_string(obj, dumper=AnsibleDumper) + self._dump_stream(obj, stream, dumper=AnsibleDumper) + + yaml_string_from_stream = stream.getvalue() + + # reset stream + stream.seek(0) + + loader = self._loader(stream) + # loader = AnsibleLoader(stream, vault_password=self.vault_password) + obj_from_stream = loader.get_data() + + stream_from_string = io.StringIO(yaml_string) + loader2 = self._loader(stream_from_string) + # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password) + obj_from_string = loader2.get_data() + + stream_obj_from_stream = io.StringIO() + stream_obj_from_string = io.StringIO() + + if PY3: + yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper) + yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper) + else: + yaml.dump( + obj_from_stream, + stream_obj_from_stream, + Dumper=AnsibleDumper, + encoding=None, + ) + yaml.dump( + obj_from_stream, + stream_obj_from_string, + Dumper=AnsibleDumper, + encoding=None, + ) + + yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue() + yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue() + + stream_obj_from_stream.seek(0) + stream_obj_from_string.seek(0) + + if PY3: + yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper) + yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper) + else: + yaml_string_obj_from_stream = yaml.dump( + obj_from_stream, Dumper=AnsibleDumper, encoding=None + ) + yaml_string_obj_from_string = yaml.dump( + obj_from_string, Dumper=AnsibleDumper, encoding=None + ) + + assert yaml_string == yaml_string_obj_from_stream + assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + assert ( + yaml_string + == yaml_string_obj_from_stream + == yaml_string_obj_from_string + == yaml_string_stream_obj_from_stream + == yaml_string_stream_obj_from_string + ) + assert obj == obj_from_stream + assert obj == obj_from_string + assert obj == yaml_string_obj_from_stream + assert obj == yaml_string_obj_from_string + assert ( + obj + == obj_from_stream + == obj_from_string + == yaml_string_obj_from_stream + == yaml_string_obj_from_string + ) + return { + "obj": obj, + "yaml_string": yaml_string, + "yaml_string_from_stream": yaml_string_from_stream, + "obj_from_stream": obj_from_stream, + "obj_from_string": obj_from_string, + "yaml_string_obj_from_string": yaml_string_obj_from_string, + } diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py new file mode 100644 index 000000000..01a0adc3f --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py @@ -0,0 +1,31 @@ +# Copyright (c) 2017 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import json + +import pytest +from ansible.module_utils._text import to_bytes +from ansible.module_utils.common._collections_compat import MutableMapping +from ansible.module_utils.six import string_types + + +@pytest.fixture +def patch_ansible_module(request, mocker): + if isinstance(request.param, string_types): + args = request.param + elif isinstance(request.param, MutableMapping): + if "ANSIBLE_MODULE_ARGS" not in request.param: + request.param = {"ANSIBLE_MODULE_ARGS": request.param} + if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]: + request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp" + if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]: + request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False + args = json.dumps(request.param) + else: + raise Exception("Malformed data to the patch_ansible_module pytest fixture") + + mocker.patch("ansible.module_utils.basic._ANSIBLE_ARGS", to_bytes(args)) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg new file mode 100644 index 000000000..74d0a43fc --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg @@ -0,0 +1 @@ +foo=bar diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg new file mode 100644 index 000000000..482c59adb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg @@ -0,0 +1 @@ +test-br diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg @@ -0,0 +1 @@ +0 diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg new file mode 100644 index 000000000..38bf3dc0e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg @@ -0,0 +1 @@ +secure diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg new file mode 100644 index 000000000..660fa5ae1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg @@ -0,0 +1 @@ +{foo=bar} diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg new file mode 100644 index 000000000..ef62fb5bd --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg @@ -0,0 +1 @@ +{bond-detect-mode=miimon} diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg new file mode 100644 index 000000000..660fa5ae1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg @@ -0,0 +1 @@ +{foo=bar} diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg @@ -0,0 +1 @@ +10 diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg new file mode 100644 index 000000000..482c59adb --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg @@ -0,0 +1 @@ +test-br diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg new file mode 100644 index 000000000..306379d4e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg @@ -0,0 +1 @@ +bond0 diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg new file mode 100644 index 000000000..a908f0da4 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg @@ -0,0 +1 @@ +eth2 diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg new file mode 100644 index 000000000..3c9dafc69 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg @@ -0,0 +1,23 @@ +_uuid : 64f04422-d510-4258-9648-ee0a982f58c1 +auto_attach : [] +controller : [] +datapath_id : "00002244f0645842" +datapath_type : "" +datapath_version : "<unknown>" +external_ids : {} +fail_mode : [] +flood_vlans : [] +flow_tables : {} +ipfix : [] +mcast_snooping_enable: false +mirrors : [] +name : test-br +netflow : [] +other_config : {} +ports : [2c9c1b35-a304-4dee-bb7a-092d656543c7] +protocols : [] +rstp_enable : false +rstp_status : {} +sflow : [] +status : {} +stp_enable : false diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg new file mode 100644 index 000000000..4b9f3a799 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg @@ -0,0 +1,23 @@ +_uuid : 64f04422-d510-4258-9648-ee0a982f58c1 +auto_attach : [] +controller : [] +datapath_id : "00002244f0645842" +datapath_type : "" +datapath_version : "<unknown>" +external_ids : {} +fail_mode : [] +flood_vlans : [] +flow_tables : {} +ipfix : [] +mcast_snooping_enable: false +mirrors : [] +name : test-br +netflow : [] +other_config : {disable-in-band=true} +ports : [2c9c1b35-a304-4dee-bb7a-092d656543c7] +protocols : [] +rstp_enable : false +rstp_status : {} +sflow : [] +status : {} +stp_enable : false diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py new file mode 100644 index 000000000..92a5e11d1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py @@ -0,0 +1,87 @@ +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import json +import os + +from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import ( + AnsibleExitJson, + AnsibleFailJson, + ModuleTestCase, +) + +fixture_path = os.path.join(os.path.dirname(__file__), "fixtures") +fixture_data = {} + + +def load_fixture(name): + path = os.path.join(fixture_path, name) + + if path in fixture_data: + return fixture_data[path] + + with open(path) as f: + data = f.read() + + try: + data = json.loads(data) + except Exception: + pass + + fixture_data[path] = data + return data + + +class TestOpenVSwitchModule(ModuleTestCase): + def execute_module(self, failed=False, changed=False, commands=None, test_name=None): + self.load_fixtures(test_name) + + if failed: + result = self.failed() + self.assertTrue(result["failed"], result) + else: + result = self.changed(changed) + self.assertEqual(result["changed"], changed, result) + + if commands is not None: + self.assertEqual(commands, result["commands"], result["commands"]) + + return result + + def failed(self): + with self.assertRaises(AnsibleFailJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertTrue(result["failed"], result) + return result + + def changed(self, changed=False): + with self.assertRaises(AnsibleExitJson) as exc: + self.module.main() + + result = exc.exception.args[0] + self.assertEqual(result["changed"], changed, result) + return result + + def load_fixtures(self, test_name): + pass diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py new file mode 100644 index 000000000..29f3eba4e --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py @@ -0,0 +1,175 @@ +# +# (c) 2020, James Denton <james.denton@outlook.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_bond +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch +from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args + +from .ovs_module import TestOpenVSwitchModule, load_fixture + +test_name_side_effect_matrix = { + "test_openvswitch_bond_absent_idempotent": [(0, "", "")], + "test_openvswitch_bond_absent_removes_bond": [ + (0, "list_ports_bond_br.cfg", ""), + (0, "get_port_bond0_other_config.cfg", ""), + (0, "get_port_bond0_external_ids.cfg", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bond_present_idempotent": [ + (0, "list_ports_bond_br.cfg", ""), + (0, "get_port_bond0_other_config.cfg", ""), + (0, "get_port_bond0_external_ids.cfg", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bond_present_creates_bond": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bond_present_creates_lacp_bond": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], +} + + +class TestOpenVSwitchBondModule(TestOpenVSwitchModule): + module = openvswitch_bond + + def setUp(self): + super(TestOpenVSwitchBondModule, self).setUp() + + self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command") + self.run_command = self.mock_run_command.start() + self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path") + self.get_bin_path = self.mock_get_bin_path.start() + + def tearDown(self): + super(TestOpenVSwitchBondModule, self).tearDown() + + self.mock_run_command.stop() + self.mock_get_bin_path.stop() + + def load_fixtures(self, test_name): + test_side_effects = [] + for s in test_name_side_effect_matrix[test_name]: + rc = s[0] + out = s[1] if s[1] == "" else str(load_fixture(s[1])) + err = s[2] + side_effect_with_fixture_loaded = (rc, out, err) + test_side_effects.append(side_effect_with_fixture_loaded) + self.run_command.side_effect = test_side_effects + + self.get_bin_path.return_value = "/usr/bin/ovs-vsctl" + + def test_openvswitch_bond_absent_idempotent(self): + set_module_args(dict(state="absent", bridge="bond-br", port="bond0")) + self.execute_module(commands=[], test_name="test_openvswitch_bond_absent_idempotent") + + def test_openvswitch_bond_absent_removes_bond(self): + set_module_args(dict(state="absent", bridge="bond-br", port="bond0")) + commands = ["/usr/bin/ovs-vsctl -t 5 del-port bond-br bond0"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bond_absent_removes_bond", + ) + + def test_openvswitch_bond_database_socket(self): + set_module_args( + dict( + state="absent", + bridge="bond-br", + port="bond0", + database_socket="unix:/opt/second.sock", + ) + ) + commands = ["/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 del-port bond-br bond0"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bond_absent_removes_bond", + ) + + def test_openvswitch_bond_present_idempotent(self): + set_module_args( + dict( + state="present", + bridge="bond-br", + port="bond0", + external_ids={"foo": "bar"}, + other_config={"bond-detect-mode": "miimon"}, + ) + ) + self.execute_module(commands=[], test_name="test_openvswitch_bond_present_idempotent") + + def test_openvswitch_bond_present_creates_bond(self): + set_module_args( + dict( + state="present", + bridge="bond-br", + port="bond0", + bond_updelay="100", + bond_downdelay="100", + interfaces=["eth3", "eth4"], + other_config={"bond-detect-mode": "miimon"}, + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-bond bond-br bond0 eth3 eth4" + + " bond_updelay=100 bond_downdelay=100", + "/usr/bin/ovs-vsctl -t 5 set port bond0 other_config:bond-detect-mode=miimon", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bond_present_creates_bond", + ) + + def test_openvswitch_bond_present_creates_lacp_bond(self): + set_module_args( + dict( + state="present", + lacp="active", + bridge="bond-br", + port="bond0", + interfaces=["eth3", "eth4"], + other_config={"bond-detect-mode": "miimon"}, + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-bond bond-br bond0 eth3 eth4 lacp=active", + "/usr/bin/ovs-vsctl -t 5 set port bond0 other_config:bond-detect-mode=miimon", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bond_present_creates_bond", + ) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py new file mode 100644 index 000000000..bd620e84c --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py @@ -0,0 +1,299 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import pytest + +from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_bridge +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock, patch +from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args + +from .ovs_module import TestOpenVSwitchModule, load_fixture + + +@pytest.fixture +def patched_openvswitch_bridge(monkeypatch): + mocked_bridge = MagicMock() + mocked_bridge.return_value = { + "bridge": "test-br2", + "parent": "test-br", + "vlan": 200, + "fail_mode": None, + "external_ids": None, + "set": None, + } + monkeypatch.setattr(openvswitch_bridge, "map_config_to_obj", mocked_bridge) + return openvswitch_bridge + + +test_name_side_effect_matrix = { + "test_openvswitch_bridge_absent_idempotent": [(0, "", "")], + "test_openvswitch_bridge_absent_removes_bridge": [ + (0, "list_br_test_br.cfg", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_idempotent": [ + (0, "list_br_test_br.cfg", ""), + (0, "br_to_parent_test_br.cfg", ""), + (0, "br_to_vlan_zero.cfg", ""), + (0, "get_fail_mode_secure.cfg", ""), + (0, "br_get_external_id_foo_bar.cfg", ""), + ], + "test_openvswitch_bridge_present_creates_bridge": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_creates_fake_bridge": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_updates_vlan": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_adds_external_id": [ + (0, "list_br_test_br.cfg", ""), + (0, "br_to_parent_test_br.cfg", ""), + (0, "br_to_vlan_zero.cfg", ""), + (0, "get_fail_mode_secure.cfg", ""), + (0, "br_get_external_id_foo_bar.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_clears_external_id": [ + (0, "list_br_test_br.cfg", ""), + (0, "br_to_parent_test_br.cfg", ""), + (0, "br_to_vlan_zero.cfg", ""), + (0, "get_fail_mode_secure.cfg", ""), + (0, "br_get_external_id_foo_bar.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_changes_fail_mode": [ + (0, "list_br_test_br.cfg", ""), + (0, "br_to_parent_test_br.cfg", ""), + (0, "br_to_vlan_zero.cfg", ""), + (0, "get_fail_mode_secure.cfg", ""), + (0, "br_get_external_id_foo_bar.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_bridge_present_runs_set_mode": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], +} + + +class TestOpenVSwitchBridgeModule(TestOpenVSwitchModule): + module = openvswitch_bridge + + def setUp(self): + super(TestOpenVSwitchBridgeModule, self).setUp() + + self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command") + self.run_command = self.mock_run_command.start() + self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path") + self.get_bin_path = self.mock_get_bin_path.start() + + def tearDown(self): + super(TestOpenVSwitchBridgeModule, self).tearDown() + + self.mock_run_command.stop() + self.mock_get_bin_path.stop() + + def load_fixtures(self, test_name): + test_side_effects = [] + for s in test_name_side_effect_matrix[test_name]: + rc = s[0] + out = s[1] if s[1] == "" else str(load_fixture(s[1])) + err = s[2] + side_effect_with_fixture_loaded = (rc, out, err) + test_side_effects.append(side_effect_with_fixture_loaded) + self.run_command.side_effect = test_side_effects + + self.get_bin_path.return_value = "/usr/bin/ovs-vsctl" + + def test_openvswitch_bridge_absent_idempotent(self): + set_module_args(dict(state="absent", bridge="test-br")) + self.execute_module(test_name="test_openvswitch_bridge_absent_idempotent") + + def test_openvswitch_bridge_absent_removes_bridge(self): + set_module_args(dict(state="absent", bridge="test-br")) + commands = ["/usr/bin/ovs-vsctl -t 5 del-br test-br"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_absent_removes_bridge", + ) + + def test_openvswitch_bridge_present_idempotent(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="secure", + external_ids={"foo": "bar"}, + ) + ) + self.execute_module(test_name="test_openvswitch_bridge_present_idempotent") + + def test_openvswitch_bridge_present_creates_bridge(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="secure", + external_ids={"foo": "bar"}, + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-br test-br", + "/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br secure", + "/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_creates_bridge", + ) + + def test_openvswitch_bridge_present_creates_fake_bridge(self): + set_module_args(dict(state="present", bridge="test-br2", parent="test-br", vlan=10)) + commands = ["/usr/bin/ovs-vsctl -t 5 add-br test-br2 test-br 10"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_creates_fake_bridge", + ) + + def test_openvswitch_bridge_uses_database_socket(self): + set_module_args( + dict( + state="present", + bridge="test-br2", + parent="test-br", + database_socket="unix:/opt/second.sock", + vlan=10, + ) + ) + commands = ["/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 add-br test-br2 test-br 10"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_creates_fake_bridge", + ) + + @pytest.mark.usefixtures("patched_openvswitch_bridge") + def test_openvswitch_bridge_updates_vlan(self): + set_module_args( + { + "state": "present", + "bridge": "test-br2", + "parent": "test-br", + "vlan": 300, + } + ) + commands = ["/usr/bin/ovs-vsctl -t 5 set port test-br2 tag=300"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_updates_vlan", + ) + + def test_openvswitch_bridge_present_adds_external_id(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="secure", + external_ids={"bip": "bop"}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br bip bop"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_adds_external_id", + ) + + def test_openvswitch_bridge_present_clears_external_id(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="secure", + external_ids={"foo": ""}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo "] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_clears_external_id", + ) + + def test_openvswitch_bridge_present_changes_fail_mode(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="standalone", + external_ids={"foo": "bar"}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br standalone"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_changes_fail_mode", + ) + + def test_openvswitch_bridge_present_runs_set_mode(self): + set_module_args( + dict( + state="present", + bridge="test-br", + fail_mode="secure", + external_ids={"foo": "bar"}, + set="bridge test-br datapath_type=netdev", + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-br test-br -- set bridge test-br datapath_type=netdev", + "/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br secure", + "/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_bridge_present_runs_set_mode", + ) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py new file mode 100644 index 000000000..6d2db5565 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py @@ -0,0 +1,328 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import pytest + +from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_db +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock, patch +from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args + +from .ovs_module import TestOpenVSwitchModule, load_fixture + + +@pytest.fixture +def patched_openvswitch_db(monkeypatch): + mocked_ovs_db = MagicMock() + mocked_ovs_db.return_value = { + "table": "open_vswitch", + "record": ".", + "col": "other_config", + "key": "pmd-cpu-mask", + "value": "0xaaa00000000", + } + monkeypatch.setattr(openvswitch_db, "map_config_to_obj", mocked_ovs_db) + return openvswitch_db + + +test_name_side_effect_matrix = { + "test_openvswitch_db_absent_idempotent": [ + (0, "openvswitch_db_disable_in_band_missing.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_absent_removes_key": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_present_idempotent": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_present_idempotent_value": [(0, None, None)], + "test_openvswitch_db_present_adds_key": [ + (0, "openvswitch_db_disable_in_band_missing.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_present_updates_key": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_present_missing_key_on_map": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_present_stp_enable": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_get_with_key": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_get_without_key": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], + "test_openvswitch_db_get_non_dict": [ + (0, "openvswitch_db_disable_in_band_true.cfg", None), + (0, None, None), + ], +} + + +class TestOpenVSwitchDBModule(TestOpenVSwitchModule): + module = openvswitch_db + + def setUp(self): + super(TestOpenVSwitchDBModule, self).setUp() + + self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command") + self.run_command = self.mock_run_command.start() + self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path") + self.get_bin_path = self.mock_get_bin_path.start() + + def tearDown(self): + super(TestOpenVSwitchDBModule, self).tearDown() + + self.mock_run_command.stop() + self.mock_get_bin_path.stop() + + def load_fixtures(self, test_name): + test_side_effects = [] + for s in test_name_side_effect_matrix[test_name]: + rc = s[0] + out = load_fixture(s[1]) if s[1] else None + err = s[2] + side_effect_with_fixture_loaded = (rc, out, err) + test_side_effects.append(side_effect_with_fixture_loaded) + self.run_command.side_effect = test_side_effects + + self.get_bin_path.return_value = "/usr/bin/ovs-vsctl" + + def test_openvswitch_db_absent_idempotent(self): + set_module_args( + dict( + state="absent", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="true", + ) + ) + self.execute_module(test_name="test_openvswitch_db_absent_idempotent") + + def test_openvswitch_db_absent_removes_key(self): + set_module_args( + dict( + state="absent", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="true", + ) + ) + self.execute_module( + changed=True, + commands=[ + "/usr/bin/ovs-vsctl -t 5 remove Bridge test-br other_config disable-in-band=true" + ], + test_name="test_openvswitch_db_absent_removes_key", + ) + + def test_openvswitch_db_absent_removes_key_no_value(self): + set_module_args( + dict( + state="absent", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + ) + ) + self.execute_module( + changed=True, + commands=["/usr/bin/ovs-vsctl -t 5 remove Bridge test-br other_config disable-in-band"], + test_name="test_openvswitch_db_absent_removes_key", + ) + + def test_openvswitch_db_present_idempotent(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="true", + ) + ) + self.execute_module(test_name="test_openvswitch_db_present_idempotent") + + @pytest.mark.usefixtures("patched_openvswitch_db") + def test_openvswitch_db_present_idempotent_value(self): + set_module_args( + { + "col": "other_config", + "key": "pmd-cpu-mask", + "record": ".", + "table": "open_vswitch", + "value": "0xaaa00000000", + } + ) + self.execute_module(test_name="test_openvswitch_db_present_idempotent_value") + + def test_openvswitch_db_present_adds_key(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="true", + ) + ) + self.execute_module( + changed=True, + commands=[ + "/usr/bin/ovs-vsctl -t 5 set Bridge test-br other_config:disable-in-band=true" + ], + test_name="test_openvswitch_db_present_adds_key", + ) + + def test_openvswitch_db_present_updates_key(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="false", + ) + ) + self.execute_module( + changed=True, + commands=[ + "/usr/bin/ovs-vsctl -t 5 set Bridge test-br other_config:disable-in-band=false" + ], + test_name="test_openvswitch_db_present_updates_key", + ) + + def test_openvswitch_uses_database_socket(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + database_socket="unix:/opt/second.sock", + value="false", + ) + ) + self.execute_module( + changed=True, + commands=[ + "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 set Bridge test-br other_config" + ":disable-in-band=false" + ], + test_name="test_openvswitch_db_present_updates_key", + ) + + def test_openvswitch_db_present_missing_key_on_map(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="other_config", + value="false", + ) + ) + self.execute_module( + failed=True, + test_name="test_openvswitch_db_present_missing_key_on_map", + ) + + def test_openvswitch_db_present_stp_enable(self): + set_module_args( + dict( + state="present", + table="Bridge", + record="test-br", + col="stp_enable", + value="true", + ) + ) + self.execute_module(changed=True, test_name="test_openvswitch_db_present_stp_enable") + + def test_openvswitch_db_get_with_key(self): + set_module_args( + dict( + state="read", + table="Bridge", + record="test-br", + col="other_config", + key="disable-in-band", + value="true", + ) + ) + self.execute_module( + changed=True, + commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br other_config:disable-in-band"], + test_name="test_openvswitch_db_get_with_key", + ) + + def test_openvswitch_db_get_without_key(self): + set_module_args( + dict( + state="read", + table="Bridge", + record="test-br", + col="other_config", + value="true", + ) + ) + self.execute_module( + changed=True, + commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br other_config"], + test_name="test_openvswitch_db_get_without_key", + ) + + def test_openvswitch_db_get_non_dict(self): + set_module_args( + dict( + state="read", + table="Bridge", + record="test-br", + col="name", + value="true", + ) + ) + self.execute_module( + changed=True, + commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br name"], + test_name="test_openvswitch_db_get_non_dict", + ) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py new file mode 100644 index 000000000..9817228be --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py @@ -0,0 +1,289 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_port +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch +from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args + +from .ovs_module import TestOpenVSwitchModule, load_fixture + +test_name_side_effect_matrix = { + "test_openvswitch_port_absent_idempotent": [(0, "", "")], + "test_openvswitch_port_absent_removes_port": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_idempotent": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_creates_port": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_changes_tag": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_changes_external_id": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_adds_external_id": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_clears_external_id": [ + (0, "list_ports_test_br.cfg", ""), + (0, "get_port_eth2_tag.cfg", ""), + (0, "get_port_eth2_external_ids.cfg", ""), + (0, "", ""), + ], + "test_openvswitch_port_present_runs_set_mode": [ + (0, "", ""), + (0, "", ""), + (0, "", ""), + ], +} + + +class TestOpenVSwitchPortModule(TestOpenVSwitchModule): + module = openvswitch_port + + def setUp(self): + super(TestOpenVSwitchPortModule, self).setUp() + + self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command") + self.run_command = self.mock_run_command.start() + self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path") + self.get_bin_path = self.mock_get_bin_path.start() + + def tearDown(self): + super(TestOpenVSwitchPortModule, self).tearDown() + + self.mock_run_command.stop() + self.mock_get_bin_path.stop() + + def load_fixtures(self, test_name): + test_side_effects = [] + for s in test_name_side_effect_matrix[test_name]: + rc = s[0] + out = s[1] if s[1] == "" else str(load_fixture(s[1])) + err = s[2] + side_effect_with_fixture_loaded = (rc, out, err) + test_side_effects.append(side_effect_with_fixture_loaded) + self.run_command.side_effect = test_side_effects + + self.get_bin_path.return_value = "/usr/bin/ovs-vsctl" + + def test_openvswitch_port_absent_idempotent(self): + set_module_args(dict(state="absent", bridge="test-br", port="eth2")) + self.execute_module(test_name="test_openvswitch_port_absent_idempotent") + + def test_openvswitch_port_absent_removes_port(self): + set_module_args(dict(state="absent", bridge="test-br", port="eth2")) + commands = ["/usr/bin/ovs-vsctl -t 5 del-port test-br eth2"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_absent_removes_port", + ) + + def test_openvswitch_port_present_idempotent(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": "bar"}, + ) + ) + self.execute_module(test_name="test_openvswitch_port_present_idempotent") + + def test_openvswitch_port_present_creates_port(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": "bar"}, + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10", + "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_creates_port", + ) + + def test_openvswitch_port_present_changes_tag(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=20, + external_ids={"foo": "bar"}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 tag=20"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_changes_tag", + ) + + def test_openvswitch_port_present_changes_external_id(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": "baz"}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=baz"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_changes_external_id", + ) + + def test_openvswitch_port_present_adds_external_id(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo2": "bar2"}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo2=bar2"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_adds_external_id", + ) + + def test_openvswitch_port_present_clears_external_id(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": None}, + ) + ) + commands = ["/usr/bin/ovs-vsctl -t 5 remove port eth2 external_ids foo"] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_clears_external_id", + ) + + def test_openvswitch_port_present_runs_set_mode(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": "bar"}, + set="port eth2 other_config:stp-path-cost=10", + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set" + " port eth2 other_config:stp-path-cost=10", + "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_runs_set_mode", + ) + + def test_openvswitch_port_present_runs_set_mode_multiple(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + tag=10, + external_ids={"foo": "bar"}, + set=[ + "port eth2 other_config:stp-path-cost=10", + "port eth2 type=patch", + ], + ) + ) + commands = [ + "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set" + " port eth2 other_config:stp-path-cost=10 -- set port eth2 type=patch", + "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_runs_set_mode", + ) + + def test_openvswitch_database_socket(self): + set_module_args( + dict( + state="present", + bridge="test-br", + port="eth2", + database_socket="unix:/opt/second.sock", + tag=10, + external_ids={"foo": "bar"}, + ) + ) + commands = [ + "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 add-port test-br eth2 tag=10", + "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 set port eth2 external_ids:foo=bar", + ] + self.execute_module( + changed=True, + commands=commands, + test_name="test_openvswitch_port_present_creates_port", + ) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py new file mode 100644 index 000000000..3c63aaecd --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py @@ -0,0 +1,53 @@ +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import json + +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + +from ansible_collections.openvswitch.openvswitch.tests.unit.compat import unittest +from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch + + +def set_module_args(args): + if "_ansible_remote_tmp" not in args: + args["_ansible_remote_tmp"] = "/tmp" + if "_ansible_keep_remote_files" not in args: + args["_ansible_keep_remote_files"] = False + + args = json.dumps({"ANSIBLE_MODULE_ARGS": args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + if "changed" not in kwargs: + kwargs["changed"] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + kwargs["failed"] = True + raise AnsibleFailJson(kwargs) + + +class ModuleTestCase(unittest.TestCase): + def setUp(self): + self.mock_module = patch.multiple( + basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json + ) + self.mock_module.start() + self.mock_sleep = patch("time.sleep") + self.mock_sleep.start() + set_module_args({}) + self.addCleanup(self.mock_module.stop) + self.addCleanup(self.mock_sleep.stop) diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt b/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt new file mode 100644 index 000000000..a9772bea1 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt @@ -0,0 +1,42 @@ +boto3 +placebo +pycrypto +passlib +pypsrp +python-memcached +pytz +pyvmomi +redis +requests +setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok) +unittest2 ; python_version < '2.7' +importlib ; python_version < '2.7' +netaddr +ipaddress +netapp-lib +solidfire-sdk-python + +# requirements for F5 specific modules +f5-sdk ; python_version >= '2.7' +f5-icontrol-rest ; python_version >= '2.7' +deepdiff + +# requirement for Fortinet specific modules +pyFMG + +# requirement for aci_rest module +xmljson + +# requirement for winrm connection plugin tests +pexpect + +# requirement for the linode module +linode-python # APIv3 +linode_api4 ; python_version > '2.6' # APIv4 + +# requirement for the gitlab module +python-gitlab +httmock + +# requirment for kubevirt modules +openshift ; python_version >= '2.7' diff --git a/ansible_collections/openvswitch/openvswitch/tox.ini b/ansible_collections/openvswitch/openvswitch/tox.ini new file mode 100644 index 000000000..0610ef989 --- /dev/null +++ b/ansible_collections/openvswitch/openvswitch/tox.ini @@ -0,0 +1,31 @@ +[tox] +minversion = 1.4.2 +envlist = linters +skipsdist = True + +[testenv] +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:black] +install_command = pip install {opts} {packages} +commands = + black -v {toxinidir} + +[testenv:linters] +install_command = pip install {opts} {packages} +commands = + black -v --diff --check {toxinidir} + flake8 {posargs} + +[testenv:venv] +commands = {posargs} + +[flake8] +# E123, E125 skipped as they are invalid PEP-8. + +show-source = True +ignore = E123,E125,E402,E501,E741,W503 +max-line-length = 160 +builtins = _ +exclude = .git,.tox,tests/unit/compat/ |