From d517d658a10b404f674fa383cc0173ef12554a2b Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 16 Apr 2021 07:08:18 +0200 Subject: [PATCH 01/63] Update galaxy.yml --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index dad76b9..812add0 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.3.0 +version: 1.3.1 readme: README.md authors: - Ansible community From 59cbe5ffe36db4ce40129bc1a93610ba99c5a134 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 16 Apr 2021 08:53:51 +0200 Subject: [PATCH 02/63] Release 1.4.0 --- changelogs/CHANGELOG.rst | 28 +++++++++++++++++++ changelogs/changelog.yaml | 28 +++++++++++++++++++ .../fragments/101-drop-requiressl-support.yml | 4 --- .../103-mysql_and_mariadb_divergence.yml | 2 -- .../fragments/108-mysql_priv_add_grant.yml | 2 -- ...d_mysql_full_version_suffix_return_var.yml | 2 -- ...ange_deprecated_connection_ parameters.yml | 2 -- galaxy.yml | 2 +- 8 files changed, 57 insertions(+), 13 deletions(-) delete mode 100644 changelogs/fragments/101-drop-requiressl-support.yml delete mode 100644 changelogs/fragments/103-mysql_and_mariadb_divergence.yml delete mode 100644 changelogs/fragments/108-mysql_priv_add_grant.yml delete mode 100644 changelogs/fragments/115-add_mysql_full_version_suffix_return_var.yml delete mode 100644 changelogs/fragments/116-change_deprecated_connection_ parameters.yml diff --git a/changelogs/CHANGELOG.rst b/changelogs/CHANGELOG.rst index a80c771..70dcb21 100644 --- a/changelogs/CHANGELOG.rst +++ b/changelogs/CHANGELOG.rst @@ -5,6 +5,34 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.0 +====== + +Release Summary +--------------- + +This is the minor release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection +that have been added after the release of ``community.mysql`` 1.3.0.' + +Major Changes +------------- + +- mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires`` option in ``community.mysql`` 2.0.0 and support will be dropped altogether in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121). + +Minor Changes +------------- + +- mysql module utils - change deprecated connection parameters ``passwd`` and ``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116). +- mysql_collection - introduce codebabse split to handle divergences between MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103). +- mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114). +- mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101). + +Bugfixes +-------- + +- mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105). + v1.3.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index c163341..33c4b2f 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -235,3 +235,31 @@ releases: - 107-mysql_user_fix_grant_on_col_handling.yml - 97-mysql_replication_deprecate_offending_terminology.yml release_date: '2021-03-08' + 1.4.0: + changes: + bugfixes: + - mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105). + major_changes: + - mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires`` + option in ``community.mysql`` 2.0.0 and support will be dropped altogether + in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121). + minor_changes: + - mysql module utils - change deprecated connection parameters ``passwd`` and + ``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116). + - mysql_collection - introduce codebabse split to handle divergences between + MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103). + - mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114). + - mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101). + release_summary: 'This is the minor release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection + + that have been added after the release of ``community.mysql`` 1.3.0.''' + fragments: + - 1.4.0.yml + - 101-drop-requiressl-support.yml + - 103-mysql_and_mariadb_divergence.yml + - 108-mysql_priv_add_grant.yml + - 115-add_mysql_full_version_suffix_return_var.yml + - 116-change_deprecated_connection_ parameters.yml + release_date: '2021-04-16' diff --git a/changelogs/fragments/101-drop-requiressl-support.yml b/changelogs/fragments/101-drop-requiressl-support.yml deleted file mode 100644 index fded3e3..0000000 --- a/changelogs/fragments/101-drop-requiressl-support.yml +++ /dev/null @@ -1,4 +0,0 @@ -minor_changes: - - mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101). -major_changes: - - mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires`` option in ``community.mysql`` 2.0.0 and support will be dropped altogether in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121). diff --git a/changelogs/fragments/103-mysql_and_mariadb_divergence.yml b/changelogs/fragments/103-mysql_and_mariadb_divergence.yml deleted file mode 100644 index 039c654..0000000 --- a/changelogs/fragments/103-mysql_and_mariadb_divergence.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- mysql_collection - introduce codebabse split to handle divergences between MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103). diff --git a/changelogs/fragments/108-mysql_priv_add_grant.yml b/changelogs/fragments/108-mysql_priv_add_grant.yml deleted file mode 100644 index 4cfd00e..0000000 --- a/changelogs/fragments/108-mysql_priv_add_grant.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105). diff --git a/changelogs/fragments/115-add_mysql_full_version_suffix_return_var.yml b/changelogs/fragments/115-add_mysql_full_version_suffix_return_var.yml deleted file mode 100644 index 3eadb46..0000000 --- a/changelogs/fragments/115-add_mysql_full_version_suffix_return_var.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114). diff --git a/changelogs/fragments/116-change_deprecated_connection_ parameters.yml b/changelogs/fragments/116-change_deprecated_connection_ parameters.yml deleted file mode 100644 index d6b0d7e..0000000 --- a/changelogs/fragments/116-change_deprecated_connection_ parameters.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- mysql module utils - change deprecated connection parameters ``passwd`` and ``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116). \ No newline at end of file diff --git a/galaxy.yml b/galaxy.yml index 812add0..61bd774 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.3.1 +version: 1.4.0 readme: README.md authors: - Ansible community From fe8f3662eb0088b813c83866b555b940ab9ece77 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 23 Apr 2021 15:08:49 +0300 Subject: [PATCH 03/63] mysql: revert changes made in PR 116 (#153) (#156) * mysql: revert changes made in PR 116 * Add changelog fragment * Fix CI * Fix CI * Fix CI * Update CI * Fix CI (cherry picked from commit 738343d64c058207f2e14aa4a03ac0cb1713304a) --- .github/workflows/ansible-test-plugins.yml | 2 +- changelogs/fragments/153-mysql_revert_connector_changes.yml | 2 ++ plugins/module_utils/mysql.py | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/153-mysql_revert_connector_changes.yml diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 7e5c33d..da79c04 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -61,7 +61,7 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 - - devel + #- devel python: - 3.6 connector: diff --git a/changelogs/fragments/153-mysql_revert_connector_changes.yml b/changelogs/fragments/153-mysql_revert_connector_changes.yml new file mode 100644 index 0000000..48c8b36 --- /dev/null +++ b/changelogs/fragments/153-mysql_revert_connector_changes.yml @@ -0,0 +1,2 @@ +bugfixes: +- mysql - revert changes of connector arguments made in pull request 116 causing the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116). diff --git a/plugins/module_utils/mysql.py b/plugins/module_utils/mysql.py index 67e0033..5af9c20 100644 --- a/plugins/module_utils/mysql.py +++ b/plugins/module_utils/mysql.py @@ -79,7 +79,7 @@ def mysql_connect(module, login_user=None, login_password=None, config_file='', if login_user is not None: config['user'] = login_user if login_password is not None: - config['password'] = login_password + config['passwd'] = login_password if ssl_cert is not None: config['ssl']['cert'] = ssl_cert if ssl_key is not None: @@ -87,7 +87,7 @@ def mysql_connect(module, login_user=None, login_password=None, config_file='', if ssl_ca is not None: config['ssl']['ca'] = ssl_ca if db is not None: - config['database'] = db + config['db'] = db if connect_timeout is not None: config['connect_timeout'] = connect_timeout if check_hostname is not None: From b3a83aa0a322e44a06f79d82786b41d20f20823a Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 23 Apr 2021 16:59:12 +0300 Subject: [PATCH 04/63] Release 1.4.1 commit (#159) --- changelogs/CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 14 ++++++++++++++ .../153-mysql_revert_connector_changes.yml | 2 -- galaxy.yml | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/153-mysql_revert_connector_changes.yml diff --git a/changelogs/CHANGELOG.rst b/changelogs/CHANGELOG.rst index 70dcb21..c03a3c6 100644 --- a/changelogs/CHANGELOG.rst +++ b/changelogs/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.1 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection +that have been added after the release of ``community.mysql`` 1.4.0. + +Bugfixes +-------- + +- mysql - revert changes of connector arguments made in pull request 116 causing the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116). + v1.4.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 33c4b2f..a8a0d28 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -263,3 +263,17 @@ releases: - 115-add_mysql_full_version_suffix_return_var.yml - 116-change_deprecated_connection_ parameters.yml release_date: '2021-04-16' + 1.4.1: + changes: + bugfixes: + - mysql - revert changes of connector arguments made in pull request 116 causing + the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116). + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection + + that have been added after the release of ``community.mysql`` 1.4.0.' + fragments: + - 1.4.1.yml + - 153-mysql_revert_connector_changes.yml + release_date: '2021-04-23' diff --git a/changelogs/fragments/153-mysql_revert_connector_changes.yml b/changelogs/fragments/153-mysql_revert_connector_changes.yml deleted file mode 100644 index 48c8b36..0000000 --- a/changelogs/fragments/153-mysql_revert_connector_changes.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- mysql - revert changes of connector arguments made in pull request 116 causing the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116). diff --git a/galaxy.yml b/galaxy.yml index 61bd774..79811d5 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.0 +version: 1.4.1 readme: README.md authors: - Ansible community From d200481305b7a4e45fb2721e0b7834aa671f30bd Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 23 Apr 2021 17:44:33 +0300 Subject: [PATCH 05/63] Update galaxy.yml (#160) --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index 79811d5..36eec42 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.1 +version: 1.4.2 readme: README.md authors: - Ansible community From 9c171588028991fc3e87316f1fa21f7d4eb357b3 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 10 Aug 2021 15:33:56 +0300 Subject: [PATCH 06/63] [stable-1] Doc commit backport (#196) * Add CONTRIBUTORS file (#166) (cherry picked from commit ac927fdb085c1068d12bf4567ae6163684344fdd) * Add documentation for privs with functions and procedures (#169) (cherry picked from commit 6bce48e77120614a87c96eb78a91e401d99f4a04) * Update README.md (#168) * Update README.md * Fix * Add MAINTAINERS file (cherry picked from commit 479edd81d1daf40b1ffbf4131fa77e05f35ae86c) * Improve wording in README (#170) * Improve wording in README * Update README.md Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) (cherry picked from commit c909aa2182421e3f2ff25cf97029470d4b3119f6) * Update REVIEW_CHECKLIST.md (#171) (cherry picked from commit 2236110bae9bf022b13477ec486b06d29fe4bd6c) * README: add a note how people can complain (#172) * README: add a note how people can complain * Change * Improve * Update README.md Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) (cherry picked from commit be4e84a92a39f999c65977a918f8dfd636e0a956) * README: fix typos (#174) (cherry picked from commit 2a80c301a64bd9e13d8e43b84f1945dac6039ae2) * README.md: Add link to IRC (#175) (cherry picked from commit 3335a95ba5f6aab6876bc83f7168ea2383933938) * README.md, CONTRIBUTING.md: add links to the Maintainer guidelines (#179) (cherry picked from commit 8fad3f85b8e9a2d62ede48535d5aeea6bfdf4d52) * Update README (#181) (cherry picked from commit 6d9288d19bc21ca11e9c19fd3e8cc91d947c5cd4) * Update README.md (#183) * Update README.md * Change IRC ref (cherry picked from commit 69012a2eb9be7f64f41d790356e4839de33824d9) * README: fix link (#184) (cherry picked from commit 8ab6ea771423936e4d992c90ae9c9200ad883da1) * README: fix the channel name (#185) (cherry picked from commit cd759924fd21f9eb48cb6d390a6a8f695eb54706) * CONTRIBUTING.md: replace the content with a link to Ansible contributing guidelines (#187) (cherry picked from commit 56a214885a9e6445a0ba864ff900245248371ea8) * Update README (#186) * Update README * Fix * Fix * Fix * Fix * Add Libera.Chat link (cherry picked from commit adb201a7950a43a38c8708d2d00853001ee11ae8) * fix typo (#190) "optoin" -> "option" (cherry picked from commit 596ba0cedbd14211c2fc1646633b7aa360546c89) * Update README.md (#191) * Update README.md * Update README.md (cherry picked from commit 6f02cb266a6768e82739ae71a80841142940624f) * Add MAINTAINING.md, update README.md (#192) (cherry picked from commit 0fabb2b77a9255bc3d15d5b37da8849098ba9f63) Co-authored-by: Alexander Skiba Co-authored-by: Baptiste Mille-Mathias --- CONTRIBUTING.md | 199 +----------------------- CONTRIBUTORS | 273 +++++++++++++++++++++++++++++++++ MAINTAINERS | 3 + MAINTAINING.md | 3 + README.md | 58 ++++++- REVIEW_CHECKLIST.md | 37 +---- plugins/doc_fragments/mysql.py | 2 +- plugins/modules/mysql_user.py | 10 ++ 8 files changed, 345 insertions(+), 240 deletions(-) create mode 100644 CONTRIBUTORS create mode 100644 MAINTAINERS create mode 100644 MAINTAINING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88207e9..edcfe55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,200 +1,3 @@ # Contributing -We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our contributions and interactions within this repository. - -If you are a committer, also refer to the [Ansible committer guidelines](https://docs.ansible.com/ansible/devel/community/committer_guidelines.html). - -## Issue tracker - -Whether you are looking for an opportunity to contribute or you found a bug and already know how to solve it, please go to the [issue tracker](https://github.com/ansible-collections/community.mysql/issues). -There you can find feature ideas to implement, reports about bugs to solve, or submit an issue to discuss your idea before implementing it which can help choose a right direction at the beginning of your work and potentially save a lot of time and effort. -Also somebody may already have started discussing or working on implementing the same or a similar idea, -so you can cooperate to create a better solution together. - -## Open pull requests - -Look through currently [open pull requests](https://github.com/ansible-collections/community.mysql/pulls). -You can help by reviewing them. Reviews help move pull requests to merge state. Some good pull requests cannot be merged only due to a lack of reviews. And it is always worth saying that good reviews are often more valuable than pull requests themselves. For more information how to provide a good review, refer to the [review checklist](REVIEW_CHECKLIST.md). - -Also, consider taking up a valuable, reviewed, but abandoned pull request which you could politely ask the original authors to complete yourself. - -## Discussions - -For open questions, broad suggestions, and other comments that will not typically fit in the scope of an issue or pull request, [discussions](https://github.com/ansible-collections/community.mysql/discussions) are available. That section provides a place to have a more open and informal conversation about any and all things related to this collection, included but not limited to future development plans, functionality explanations and feature proposals that are not yet fleshed out enough for an issue of their own. - -## Looking for an idea to implement - -First, see the paragraphs above. - -If you came up with a new feature, it is always worth creating an issue -before starting to write code to discuss the idea with the community first. -If you are going to implement the feature yourself, say it in the issue explicitly to avoid working in parallel with somebody else. - -## Step-by-step guide how to get into development quickly - -We assume that you use Linux as a work environment (you can use a virtual machine as well) and have `git` installed. - -1. If possible, make sure that you have installed and started `docker`. While you can also run tests without docker, this makes it a lot easier since you do not have to install the precise requirements, and tests are running properly isolated and in the exact same environments as in CI. You often can also use `podman` with the `docker` executable shim, so if you have that you probably do not need to install `docker`. - -2. Clone the [ansible-core](https://github.com/ansible/ansible) repository: -```bash -git clone https://github.com/ansible/ansible.git -``` - -Instead of installing ansible-core from source, you can also work with an already existing installation of Ansible, ansible-base or ansible-core. Simply skip steps 2 and 3 in that case. - -3. Go to the cloned repository and prepare the environment: -```bash -cd ansible && source hacking/env-setup -pip install -r requirements.txt -cd ~ -``` -4. Create the following directories in your home directory: -```bash -mkdir -p ~/ansible_collections/community/mysql -``` - -5. Fork the `community.mysql` repository through the GitHub web interface. - -6. Clone the forked repository from your profile to the created path: -```bash -git clone https://github.com/YOURACC/community.mysql.git ~/ansible_collections/community/mysql -``` - -If you prefer to use the SSH protocol: -```bash -git clone git@github.com:YOURACC/community.mysql.git ~/ansible_collections/community/mysql -``` - - -7. Go to your new cloned repository. -```bash -cd ~/ansible_collections/community/mysql -``` - -8. Be sure you are in the main branch: -```bash -git status -``` - -9. Show remotes. There should be the `origin` repository only: -```bash -git remote -v -``` - -10. Add the `upstream` repository: -```bash -git remote add upstream https://github.com/ansible-collections/community.mysql.git -``` - -11. Update your local `main` branch: -```bash -git fetch upstream -git rebase upstream/main -``` - -12. Create a branch for your changes: -```bash -git checkout -b name_of_my_branch -``` - -13. We recommend you start with writing integration tests if applicable. - -Note: If there are any difficulties with writing the tests or you are not sure if the case can be covered, feel free to skip this step. -If needed, other contributors can help you with it later. - -All integration tests are stored in `tests/integration/targets` subdirectories. -Go to the subdirectory containing the name of module you are going to change. -For example, if you are fixing the `mysql_user` module, its tests are in `tests/integration/targets/test_mysql_user/tasks`. - -The `main.yml` file holds test tasks and includes other test files. -Look for a suitable test file to integrate your tests or create and include a dedicated test file. -You can use one of the existing test files as a draft. - -When fixing a bug, write a task which reproduces the bug from the issue. - -Put the reported case in the tests, then run integration tests with the following command: -```bash -ansible-test integration test_mysql_user --docker -vvv -``` -If the tests do not want to run, first, check you complete step 3 of this guide. - -If the tests ran successfully, there are usually two possible outcomes: -a) If the bug has not appeared and the tests have passed successfully, ask the reporter to provide more details. The bug can be not a bug actually or can relate to a particular software version used or specifics of local environment configuration. - -b) The bug has appeared and the tests has failed as expected showing the reported symptoms. - -14. Fix the bug. - -15. Run `flake8` against a changed file. If it is `plugins/modules/mysql_user.py`: -```bash -flake8 plugins/modules/mysql_user.py -``` -It is worth installing and running `flake8` against the changed file(s) first. -It shows unused imports, which is not shown by sanity tests (see the next step), as well as other common issues. -Optionally, you can use the `--max-line-length=160` command-line argument. - -16. Run sanity tests: -```bash -ansible-test sanity plugins/modules/mysql_user.py --docker -``` -If they failed, look at the output carefully - it is usually very informative and helps to identify a problem line quickly. -Sanity failings usually relate to wrong code and documentation formatting. - -17. Run integration tests: -```bash -ansible-test integration test_mysql_user --docker -vvv -``` - -There are two possible outcomes: -a) They have failed. Look at the output of the command. -Fix the problem place in the code and run again. -Repeat the cycle until the tests pass. - -b) They have passed. Remember they failed originally? Our congratulations! You have fixed the bug. - -18. Commit your changes with an informative but short commit message: -```bash -git add /path/to/changed/file -git commit -m "mysql_user: fix crash when ..." -``` - -19. Push the branch to the `origin` (your fork): -```bash -git push origin name_of_my_branch -``` - -20. Go to the `upstream` (http://github.com/ansible-collections/community.mysql). - -21. Go to `Pull requests` tab and create a pull request. - -GitHub is tracking your fork, so it should see the new branch in it and automatically offer -to create a pull request. Sometimes GitHub does not do it and you should click the `New pull request` button yourself. -Then choose `compare across forks` under the `Compare changes` title. -Choose your repository and the new branch you pushed in the right drop-down list. -Confirm. Fill out the pull request template with all information you want to mention. -Put "Fixes + link to the issue" in the pull request's description. -Put "[WIP] + short description" in the pull request's title. It's often a good idea to mention the name of the module/plugin you are modifying at the beginning of the description. -Click `Create pull request`. - -22. Add a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#changelogs) to the `changelog/fragments` directory. It will be published in release notes, so users will know about the fix. - -Commit and push it: -```bash -git add changelog/fragments/myfragment.yml -git commit -m "Add changelog fragment" -git push origin name_of_my_branch -``` - -23. The CI tests will run automatically on Red Hat infrastructure after every commit. - -You will see the CI status in the bottom of your pull request. -If they are green, remove "[WIP]" from the title. Mention the issue reporter in a comment and let contributors know that the pull request is "Ready for review". - -24. Wait for reviews. You can also ask for review on IRC in the #ansible-community channel. - -25. If the pull request looks good to the community, committers will merge it. - -For details, refer to the [Ansible developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html). - -If you find any inconsistencies or places in this document which can be improved, feel free to raise an issue or pull request to fix it. +Refer to the [Ansible Contributing guidelines](https://github.com/ansible/community-docs/blob/main/contributing.rst) to learn how to contribute to this collection. diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..7678773 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,273 @@ +116davinder +20 +28 +29 +4 +4n70w4 +abadger +abondis +acozine +adamchainz +adq +Akasurde +Alexander198961 +alustenberg +aminvakil +amitk79 +amree +Andersson007 +andrewhowdencom +ansibot +anthonyxpalermo +antonioribeiro +apollo13 +aquach +arcmop +asad-at-srt +AshDevilRed +aurimasl +axelll +axisK +azielke +baldpale +banyek +BarbzYHOOL +Berbe +bjne +bmalynovytch +bmildren +boreal321 +brutus +burner1024 +calfonso +candeira +caphrim007 +cdalbergue +checkphi +chrismeyersfsu +ChristopherGAndrews +cmodijk +codeaken +codebymikey +coreylane +CormacBracken +cosmix +cptMikky +crashes +dagwieers +damianmoore +Davidffry +denisemauldin +diclophis +d-lee +dmp1ce +dnelson +dramaley +drybjed +drzraf +DSpeichert +dungdm93 +dwagelaar +dylanjbarth +einarc +E-M +eowin +Ernest0x +esamattis +Everspace +F21 +faitno +felixfontein +flatrocks +fourjay +fraff +g00fy- +geerlingguy +georgeOsdDev +ghjm +ghost +giacmir +giorgio-v +gkoller +gottwald +gstorme +gundalow +hansbaer +hchargois +hluaces +hwali +hyperfocus1338 +igormukhingmailcom +imjoseangel +infigoKriti +ipergenitsa +iredmail +ivandigiusto +jadbaz +jaikdean +jamescassell +janosmiko +jarnold-timeout +JaSafieddine +jborean93 +jctanner +jean-christophe-manciot +Jean-Daniel +jgornick +jhagg +jhoekx +jirib +jkleckner +jkordish +jlaska +Jmainguy +jochu +JoelFeiner +johnavp1989 +jonatasbaldin +Jorge-Rodriguez +jpjaatin +jpmens +JSafieddine +jsmartin +juergenhoetzel +jw34 +kalaisubbiah +kenichi-ogawa-1988 +kkeane +klingac +kotso +kuntalFreshBooks +kurtdavis +larsks +ldesgrange +leeadh +LeonB +leucos +loomsen +lorin +lowwalker +lperezs +makmanalp +manuelmorena +MarcinOrlowski +markdorison +markotitel +marktheunissen +markuman +mattclay +matt-horwood-mayden +mavimo +maxamillion +maxbube +mcgoldrickm +meanstrong +meersjo +megamisan +michaeldg +michalmedvecky +MikeiLL +milky-milk +milosz +mistaka0s +mklassen +mkrizek +mmoya +mohag +mohsenSy +mpdehaan +MRwangyd +mverwijs +mvgrimes +mysqlbox +netmonk +nhojpatrick +nicolas-g +NielsH +nitinkansal1984 +nitzmahone +Ompragash +on +order +organman91 +p53 +pakal +paulbadcock +pennycoders +petoju +petracvv +pgrenaud +philfry +pileofrogs +pkaramol +platypus-geek +plumbeo +pratikgadiya12 +pshanbhag +r0bj +rajsshah86 +reduzent +relrod +resmo +ricco24 +richlv +riupie +rndmh3ro +robertdebock +robpblake +rokka-n +Roxyrob +roysmith +rthouvenin +ruudk +samccann +samdoran +sayap +scottbrown +seanorama +sedrubal +sergey-trukhin +Shaps +shrikeh +sivel +skalfyfan +skoriy88 +sperantus +spoyd +steverweber +steveteahan +stijnopheide +stintel +stoned +strixBE +SWADESNA +tapologo +tejatsk14 +tersmitten +the +the02 +thomasliddledba +time-palominodb +timorunge +Tomasthanes +tomdymond +Tronde +tvlooy +tyll +UncertaintyP +vamshi8 +vanne +vdboor +vmahadev +v-zhuravlev +webmat +wedi +whysthatso +willthames +windowsansiblernew +wrosario +xiata +Xyon +yangchao0512 +ziegenberg +Zverik diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..c520538 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,3 @@ +bmalynovytch +Jorge-Rodriguez +Andersson007 (andersson007_ in #ansible-community IRC) diff --git a/MAINTAINING.md b/MAINTAINING.md new file mode 100644 index 0000000..9fad0d3 --- /dev/null +++ b/MAINTAINING.md @@ -0,0 +1,3 @@ +# Maintaining this collection + +Refer to the [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst). diff --git a/README.md b/README.md index b1bd9d2..8d1349e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,46 @@ # MySQL collection for Ansible [![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) +This collection is a part of the Ansible package. + +## Code of Conduct + +We follow the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our interactions within this project. + +If you encounter abusive behavior violating the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html), please refer to the [policy violations](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html#policy-violations) section of the Code of Conduct for information on how to raise a complaint. + +## Contributing + +The content of this collection is made by [people](https://github.com/ansible-collections/community.mysql/blob/main/CONTRIBUTORS) just like you, a community of individuals collaborating on making the world better through developing automation software. + +We are actively accepting new contributors. + +Any kind of contribution is very welcome. + +You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.mysql/blob/main/CONTRIBUTING.md)! + +## Collection maintenance + +The current maintainers (contributors with `write` or higher access) are listed in the [MAINTAINERS](https://github.com/ansible-collections/community.mysql/blob/main/MAINTAINERS) file. If you have questions or need help, feel free to mention them in the proposals. + +To learn how to maintain / become a maintainer of this collection, refer to the [Maintainer guidelines](https://github.com/ansible-collections/community.mysql/blob/main/MAINTAINING.md). + +## Communication + +We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). Be sure you are subscribed. + +Join us in the `#ansible` (general use questions and support), `#ansible-community` (community and collection development questions), and other [IRC channels](https://docs.ansible.com/ansible/devel/community/communication.html#irc-channels) on [Libera.Chat](https://libera.chat). + +We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us. + +For more information about communication, refer to the [Ansible Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html). + +## Governance + +The process of decision making in this collection is based on discussing and finding consensus among participants. + +Every voice is important and every idea is valuable. If you have something on your mind, create an issue or dedicated discussion and let's discuss it! + ## Included content - **Modules**: @@ -20,7 +60,7 @@ ## External requirements -The MySQL modules rely on a MySQL connector. The list of supported drivers is below: +The MySQL modules rely on a MySQL connector. The list of supported drivers is below: - [PyMySQL](https://github.com/PyMySQL/PyMySQL) - [MySQLdb](https://github.com/PyMySQL/mysqlclient-python) @@ -44,12 +84,20 @@ collections: - name: community.mysql ``` +Note that if you install the collection from Ansible Galaxy, it will not be upgraded automatically if you upgrade the Ansible package. To upgrade the collection to the latest available version, run the following command: + +```bash +ansible-galaxy collection install community.mysql --upgrade +``` + +You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax: + +```bash +ansible-galaxy collection install community.mysql:==2.0.0 +``` + See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. -## Contributing - -See the [contribution guide](CONTRIBUTING.md). - ## Licensing diff --git a/REVIEW_CHECKLIST.md b/REVIEW_CHECKLIST.md index 3ea3440..9dccf7e 100644 --- a/REVIEW_CHECKLIST.md +++ b/REVIEW_CHECKLIST.md @@ -1,38 +1,3 @@ # Review Checklist -When reviewing, keep in mind that we follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our contributions and interactions within this repository. - -If you are a committer, also refer to the [Ansible committer guidelines](https://docs.ansible.com/ansible/devel/community/committer_guidelines.html). - -**General tips** -- Try to create a culture of collaboration when reviewing -- Welcome the author and thank them for the pull request -- When suggesting changes, try to use questions, not statements -- When suggesting mandatory changes, do it as politely as possible providing documentation references -- If your suggestion is optional or a matter of personal preferences, please say it explicitly -- When asking for adding tests or for complex code refactoring, say that the author is welcome to ask for clarifications and help if they need -- If somebody suggests a good idea, mention it or put a thumbs up -- After merging, thank the author and reviewers for their time and effort - -**Standards and documentation** -- [ ] if the pull request is not a documentation fix, it must include a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#creating-a-changelog-fragment) - please check the format carefully -- [ ] if new files are added with the pull request, they follow the [licensing rules](https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#licensing) -- [ ] the changes follow the [Ansible documentation standards](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html) and the [style guide](https://docs.ansible.com/ansible/devel/dev_guide/style_guide/index.html#style-guide) -- [ ] the changes follow the [development conventions](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html) -- [ ] if a new plugin is added, it is one of the [allowed plugin types](https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins) -- [ ] documentation, examples, and return sections use FQCNs for the `M(..)` [format macros](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#linking-and-other-format-macros-within-module-documentation) when referring to modules -- [ ] modules and plugins from ansible-core use `ansible.builtin.` as a FQCN prefix when mentioned -- [ ] when a new option, module, plugin, or return value is added, the corresponding documentation or return sections use `version_added:` containing the *collection* version which they will be first released in - * this usually is the next minor release, sometimes the next major release (example: if 2.7.5 is the current release, the next minor release will be 2.8.0, and the next major release will be 3.0.0) -- [ ] FQCNs are used for `extends_documentation_fragment:`, unless the author is referring to doc_fragments from ansible-core - -**Tests (if applicable and technically possible to implement)** -- [ ] the pull request has [integration tests](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html) -- [ ] the pull request has [unit tests](https://docs.ansible.com/ansible/devel/dev_guide/testing_units.html) -- [ ] all changes are covered -- [ ] integration tests also cover `check_mode` (if it is supported) -- [ ] integration tests check an actual state of the system, not only what the module reports (for example, if the module changes a file, check that the file was actually changed by using the `ansible.builtin.stat` module) - -**Other** -- [ ] the pull request does not contain merge commits (see GitHub warnings at the bottom of the pull request) - in this case, ask the author to rebase the pull request branch -- [ ] if the pull request contains breaking changes, ask the author and the collection maintainers if it is really needed and there is no way not to introduce them +Refer to the [Collection review checklist](https://github.com/ansible/community-docs/blob/main/review_checklist.rst). diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index 6d7a546..b7a9152 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -67,7 +67,7 @@ options: - Whether to validate the server host name when an SSL connection is required. Corresponds to MySQL CLIs C(--ssl) switch. - Setting this to C(false) disables hostname verification. Use with caution. - Requires pymysql >= 0.7.11. - - This optoin has no effect on MySQLdb. + - This option has no effect on MySQLdb. type: bool version_added: '1.1.0' requirements: diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index b39b11a..38c1a55 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -53,6 +53,7 @@ options: the module will always report changes. It includes grouping columns by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))). - Can be passed as a dictionary (see the examples). + - Supports GRANTs for procedures and functions (see the examples). type: raw append_privs: description: @@ -188,6 +189,15 @@ EXAMPLES = r''' 'db1.*': 'ALL,GRANT' 'db2.*': 'ALL,GRANT' +# Use 'PROCEDURE' instead of 'FUNCTION' to apply GRANTs for a MySQL procedure instead. +- name: Grant a user the right to execute a function + community.mysql.mysql_user: + name: readonly + password: 12345 + priv: + FUNCTION my_db.my_function: EXECUTE + state: present + # Note that REQUIRESSL is a special privilege that should only apply to *.* by itself. # Setting this privilege in this manner is deprecated. # Use 'tls_requires' instead. From 64b06aa543d6ed9619fa3a6d58a8b169208183b2 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 10 Aug 2021 16:38:37 +0300 Subject: [PATCH 07/63] mysql_query: correctly reflect changed status in replace statements (#193) (#197) * mysql_query: correctly reflect changed status in replace statements. * Fix the wrong indent. (cherry picked from commit 9055bb4c8c95aede61e7ebe4aa21d7c6217b4a80) Co-authored-by: Tong He <68936428+unnecessary-username@users.noreply.github.com> --- CONTRIBUTORS | 1 + ...t_changed_status_in_replace_statements.yml | 2 ++ plugins/modules/mysql_query.py | 2 +- .../test_mysql_query/defaults/main.yml | 1 + .../tasks/mysql_query_initial.yml | 32 +++++++++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 7678773..718caa2 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -255,6 +255,7 @@ Tronde tvlooy tyll UncertaintyP +unnecessary-username vamshi8 vanne vdboor diff --git a/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml b/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml new file mode 100644 index 0000000..8ce0461 --- /dev/null +++ b/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml @@ -0,0 +1,2 @@ +minor_changes: +- mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193). \ No newline at end of file diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index ed3ace4..fc789c5 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -112,7 +112,7 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import ( ) from ansible.module_utils._text import to_native -DML_QUERY_KEYWORDS = ('INSERT', 'UPDATE', 'DELETE') +DML_QUERY_KEYWORDS = ('INSERT', 'UPDATE', 'DELETE', 'REPLACE') # TRUNCATE is not DDL query but it also returns 0 rows affected: DDL_QUERY_KEYWORDS = ('CREATE', 'DROP', 'ALTER', 'RENAME', 'TRUNCATE') diff --git a/tests/integration/targets/test_mysql_query/defaults/main.yml b/tests/integration/targets/test_mysql_query/defaults/main.yml index 51a3bd7..4ee25ff 100644 --- a/tests/integration/targets/test_mysql_query/defaults/main.yml +++ b/tests/integration/targets/test_mysql_query/defaults/main.yml @@ -7,6 +7,7 @@ test_db: testdb test_table1: test1 test_table2: test2 test_table3: test3 +test_table4: test4 test_script_path: /tmp/test.sql user_name_1: 'db_user1' diff --git a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml index b01de55..30182fe 100644 --- a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml +++ b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml @@ -289,6 +289,38 @@ - result is failed - result.msg is search('the elements in query list must be strings') + - name: Create {{ test_table4 }} + mysql_query: + <<: *mysql_params + login_db: '{{ test_db }}' + query: 'CREATE TABLE {{ test_table4 }} (id int primary key, story text)' + + - name: Insert test data using replace statement + mysql_query: + <<: *mysql_params + login_db: '{{ test_db }}' + query: "REPLACE INTO {{ test_table4 }} VALUES (1, 'first')" + single_transaction: yes + register: result + + - assert: + that: + - result is changed + - result.rowcount == [1] + + - name: Replace test data + mysql_query: + <<: *mysql_params + login_db: '{{ test_db }}' + query: "REPLACE INTO {{ test_table4 }} VALUES (1, 'one')" + single_transaction: yes + register: result + + - assert: + that: + - result is changed + - result.rowcount == [2] + - name: Drop db {{ test_db }} mysql_query: <<: *mysql_params From f49206d3b32772fc65f4aa8f0213f9b7d85af81d Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Wed, 11 Aug 2021 09:38:59 +0300 Subject: [PATCH 08/63] Release 1.4.2 commit (#198) --- changelogs/CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 13 +++++++++++++ ...flect_changed_status_in_replace_statements.yml | 2 -- 3 files changed, 28 insertions(+), 2 deletions(-) delete mode 100644 changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml diff --git a/changelogs/CHANGELOG.rst b/changelogs/CHANGELOG.rst index c03a3c6..8390944 100644 --- a/changelogs/CHANGELOG.rst +++ b/changelogs/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.2 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.1. + +Minor Changes +------------- + +- mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193). + v1.4.1 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index a8a0d28..ef8a93b 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -277,3 +277,16 @@ releases: - 1.4.1.yml - 153-mysql_revert_connector_changes.yml release_date: '2021-04-23' + 1.4.2: + changes: + minor_changes: + - mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193). + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.1.' + fragments: + - 1.4.2.yml + - 193-reflect_changed_status_in_replace_statements.yml + release_date: '2021-08-11' diff --git a/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml b/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml deleted file mode 100644 index 8ce0461..0000000 --- a/changelogs/fragments/193-reflect_changed_status_in_replace_statements.yml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: -- mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193). \ No newline at end of file From dbcc7e7e60fbd0f600e213da69b1291679c23168 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 20 Aug 2021 10:50:34 +0300 Subject: [PATCH 09/63] [stable-1] mysql_info: fix TypeError failure when there are databases that do not contain tables (#209) * mysql_info: fix TypeError failure when there are databases that do not contain tables (#205) * mysql_info: fix TypeError failure when there are databases that do not contain tables * Add changelog fragment (cherry picked from commit a1f419d5413f198ace0e837d01e68ee1abb142fc) * Fix sanity errors --- ..._info_fix_failure_when_no_tables_in_db.yml | 2 ++ plugins/modules/mysql_info.py | 3 +++ plugins/modules/mysql_user.py | 2 +- .../targets/test_mysql_info/tasks/main.yml | 22 +++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml diff --git a/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml b/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml new file mode 100644 index 0000000..fd9260e --- /dev/null +++ b/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml @@ -0,0 +1,2 @@ +bugfixes: +- mysql_info - fix TypeError failure when there are databases that do not contain tables (https://github.com/ansible-collections/community.mysql/issues/204). diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 7380b6b..6f57403 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -474,6 +474,9 @@ class MySQL_Info(object): self.info['databases'][db['name']] = {} if not exclude_fields or 'db_size' not in exclude_fields: + if db['size'] is None: + db['size'] = 0 + self.info['databases'][db['name']]['size'] = int(db['size']) # If empty dbs are not needed in the returned dict, exit from the method diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 38c1a55..0bea295 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -389,7 +389,7 @@ def sanitize_requires(tls_requires): if tls_requires: for key in tls_requires.keys(): sanitized_requires[key.upper()] = tls_requires[key] - if any([key in ["CIPHER", "ISSUER", "SUBJECT"] for key in sanitized_requires.keys()]): + if any(key in ["CIPHER", "ISSUER", "SUBJECT"] for key in sanitized_requires.keys()): sanitized_requires.pop("SSL", None) sanitized_requires.pop("X509", None) return sanitized_requires diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index 785e814..0ed2af9 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -191,3 +191,25 @@ state: absent - include: issue-28.yml + + # https://github.com/ansible-collections/community.mysql/issues/204 + - name: Create database containing only views + mysql_db: + <<: *mysql_params + name: allviews + + - name: Create view + mysql_query: + <<: *mysql_params + login_db: allviews + query: 'CREATE VIEW v_today (today) AS SELECT CURRENT_DATE' + + - name: Fetch info + mysql_info: + <<: *mysql_params + register: result + + - name: Check + assert: + that: + result.databases.allviews.size == 0 From e5919428f1f50ca475a1c8c10d6ff1b53e5559d2 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 23 Sep 2021 15:07:17 +0300 Subject: [PATCH 10/63] Update README.md (#216) (#221) (cherry picked from commit 4de0e25ea0eed0264763c43a73a10244dc7c1889) --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 8d1349e..d1cee9f 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,13 @@ The current maintainers (contributors with `write` or higher access) are listed To learn how to maintain / become a maintainer of this collection, refer to the [Maintainer guidelines](https://github.com/ansible-collections/community.mysql/blob/main/MAINTAINING.md). +It is necessary for maintainers of this collection to be subscribed to: + +* The collection itself (the `Watch` button -> `All Activity` in the upper right corner of the repository's homepage). +* The "Changes Impacting Collection Contributors and Maintainers" [issue](https://github.com/ansible-collections/overview/issues/45). + +They also should be subscribed to Ansible's [The Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn). + ## Communication We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). Be sure you are subscribed. From ace830ef56e5f433be0705d2d9cd417cffff81dd Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 23 Sep 2021 15:29:24 +0300 Subject: [PATCH 11/63] Release 1.4.3 commit (#222) --- changelogs/CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 14 ++++++++++++++ ...ysql_info_fix_failure_when_no_tables_in_db.yml | 2 -- galaxy.yml | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml diff --git a/changelogs/CHANGELOG.rst b/changelogs/CHANGELOG.rst index 8390944..2a7001c 100644 --- a/changelogs/CHANGELOG.rst +++ b/changelogs/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.3 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.2. + +Bugfixes +-------- + +- mysql_info - fix TypeError failure when there are databases that do not contain tables (https://github.com/ansible-collections/community.mysql/issues/204). + v1.4.2 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index ef8a93b..3d7605a 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -290,3 +290,17 @@ releases: - 1.4.2.yml - 193-reflect_changed_status_in_replace_statements.yml release_date: '2021-08-11' + 1.4.3: + changes: + bugfixes: + - mysql_info - fix TypeError failure when there are databases that do not contain + tables (https://github.com/ansible-collections/community.mysql/issues/204). + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.2.' + fragments: + - 1.4.3.yml + - 205-mysql_info_fix_failure_when_no_tables_in_db.yml + release_date: '2021-09-23' diff --git a/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml b/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml deleted file mode 100644 index fd9260e..0000000 --- a/changelogs/fragments/205-mysql_info_fix_failure_when_no_tables_in_db.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- mysql_info - fix TypeError failure when there are databases that do not contain tables (https://github.com/ansible-collections/community.mysql/issues/204). diff --git a/galaxy.yml b/galaxy.yml index 36eec42..3c7a553 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.2 +version: 1.4.3 readme: README.md authors: - Ansible community From 9386045797d5dce701a08d937a908943d5cadc21 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 18 Jan 2022 12:53:09 +0300 Subject: [PATCH 12/63] [stable-1] Use vendored version of distutils.version (#274) * Prepare for distutils.version being removed in Python 3.12 (#267) * Prepare for distutils.version being removed in Python 3.12 * Update plugins/module_utils/version.py Co-authored-by: Felix Fontein Co-authored-by: Felix Fontein (cherry picked from commit d9e12b85ad8f73b83de6a1a039ae2fe37e021225) * Use vendored version of distutils.version (#269) * Use vendored version of distutils.version * Correct fragment * Update plugins/module_utils/version.py Co-authored-by: Felix Fontein Co-authored-by: Felix Fontein (cherry picked from commit 9c575b4762d7906c0d6d1611c3d0d3681807cdd4) * Add ignore-2.13.txt --- .../267-prepare_for_distutils_be_removed.yml | 2 + plugins/module_utils/_version.py | 343 ++++++++++++++++++ .../implementations/mariadb/replication.py | 2 +- .../implementations/mariadb/user.py | 2 +- .../implementations/mysql/replication.py | 2 +- .../implementations/mysql/user.py | 2 +- plugins/module_utils/version.py | 16 + plugins/modules/mysql_replication.py | 2 +- tests/sanity/ignore-2.13.txt | 8 + 9 files changed, 374 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/267-prepare_for_distutils_be_removed.yml create mode 100644 plugins/module_utils/_version.py create mode 100644 plugins/module_utils/version.py create mode 100644 tests/sanity/ignore-2.13.txt diff --git a/changelogs/fragments/267-prepare_for_distutils_be_removed.yml b/changelogs/fragments/267-prepare_for_distutils_be_removed.yml new file mode 100644 index 0000000..190b178 --- /dev/null +++ b/changelogs/fragments/267-prepare_for_distutils_be_removed.yml @@ -0,0 +1,2 @@ +bugfixes: +- Collection core functions - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269). diff --git a/plugins/module_utils/_version.py b/plugins/module_utils/_version.py new file mode 100644 index 0000000..59ee9db --- /dev/null +++ b/plugins/module_utils/_version.py @@ -0,0 +1,343 @@ +# Vendored copy of distutils/version.py from CPython 3.9.5 +# +# Implements multiple version numbering conventions for the +# Python Module Distribution Utilities. +# +# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0) +# + +"""Provides classes to represent module version numbers (one class for +each style of version numbering). There are currently two such classes +implemented: StrictVersion and LooseVersion. + +Every version number class implements the following interface: + * the 'parse' method takes a string and parses it to some internal + representation; if the string is an invalid version number, + 'parse' raises a ValueError exception + * the class constructor takes an optional string argument which, + if supplied, is passed to 'parse' + * __str__ reconstructs the string that was passed to 'parse' (or + an equivalent string -- ie. one that will generate an equivalent + version number instance) + * __repr__ generates Python code to recreate the version number instance + * _cmp compares the current instance with either another instance + of the same class or a string (which will be parsed to an instance + of the same class, thus must follow the same rules) +""" + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import re + +try: + RE_FLAGS = re.VERBOSE | re.ASCII +except AttributeError: + RE_FLAGS = re.VERBOSE + + +class Version: + """Abstract base class for version numbering classes. Just provides + constructor (__init__) and reproducer (__repr__), because those + seem to be the same for all version numbering classes; and route + rich comparisons to _cmp. + """ + + def __init__(self, vstring=None): + if vstring: + self.parse(vstring) + + def __repr__(self): + return "%s ('%s')" % (self.__class__.__name__, str(self)) + + def __eq__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c == 0 + + def __lt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c < 0 + + def __le__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c <= 0 + + def __gt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c > 0 + + def __ge__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c >= 0 + + +# Interface for version-number classes -- must be implemented +# by the following classes (the concrete ones -- Version should +# be treated as an abstract class). +# __init__ (string) - create and take same action as 'parse' +# (string parameter is optional) +# parse (string) - convert a string representation to whatever +# internal representation is appropriate for +# this style of version numbering +# __str__ (self) - convert back to a string; should be very similar +# (if not identical to) the string supplied to parse +# __repr__ (self) - generate Python code to recreate +# the instance +# _cmp (self, other) - compare two version numbers ('other' may +# be an unparsed version string, or another +# instance of your version class) + + +class StrictVersion(Version): + """Version numbering for anal retentives and software idealists. + Implements the standard interface for version number classes as + described above. A version number consists of two or three + dot-separated numeric components, with an optional "pre-release" tag + on the end. The pre-release tag consists of the letter 'a' or 'b' + followed by a number. If the numeric components of two version + numbers are equal, then one with a pre-release tag will always + be deemed earlier (lesser) than one without. + + The following are valid version numbers (shown in the order that + would be obtained by sorting according to the supplied cmp function): + + 0.4 0.4.0 (these two are equivalent) + 0.4.1 + 0.5a1 + 0.5b3 + 0.5 + 0.9.6 + 1.0 + 1.0.4a3 + 1.0.4b1 + 1.0.4 + + The following are examples of invalid version numbers: + + 1 + 2.7.2.2 + 1.3.a4 + 1.3pl1 + 1.3c4 + + The rationale for this version numbering system will be explained + in the distutils documentation. + """ + + version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', + RE_FLAGS) + + def parse(self, vstring): + match = self.version_re.match(vstring) + if not match: + raise ValueError("invalid version number '%s'" % vstring) + + (major, minor, patch, prerelease, prerelease_num) = \ + match.group(1, 2, 4, 5, 6) + + if patch: + self.version = tuple(map(int, [major, minor, patch])) + else: + self.version = tuple(map(int, [major, minor])) + (0,) + + if prerelease: + self.prerelease = (prerelease[0], int(prerelease_num)) + else: + self.prerelease = None + + def __str__(self): + if self.version[2] == 0: + vstring = '.'.join(map(str, self.version[0:2])) + else: + vstring = '.'.join(map(str, self.version)) + + if self.prerelease: + vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) + + return vstring + + def _cmp(self, other): + if isinstance(other, str): + other = StrictVersion(other) + elif not isinstance(other, StrictVersion): + return NotImplemented + + if self.version != other.version: + # numeric versions don't match + # prerelease stuff doesn't matter + if self.version < other.version: + return -1 + else: + return 1 + + # have to compare prerelease + # case 1: neither has prerelease; they're equal + # case 2: self has prerelease, other doesn't; other is greater + # case 3: self doesn't have prerelease, other does: self is greater + # case 4: both have prerelease: must compare them! + + if (not self.prerelease and not other.prerelease): + return 0 + elif (self.prerelease and not other.prerelease): + return -1 + elif (not self.prerelease and other.prerelease): + return 1 + elif (self.prerelease and other.prerelease): + if self.prerelease == other.prerelease: + return 0 + elif self.prerelease < other.prerelease: + return -1 + else: + return 1 + else: + raise AssertionError("never get here") + +# end class StrictVersion + +# The rules according to Greg Stein: +# 1) a version number has 1 or more numbers separated by a period or by +# sequences of letters. If only periods, then these are compared +# left-to-right to determine an ordering. +# 2) sequences of letters are part of the tuple for comparison and are +# compared lexicographically +# 3) recognize the numeric components may have leading zeroes +# +# The LooseVersion class below implements these rules: a version number +# string is split up into a tuple of integer and string components, and +# comparison is a simple tuple comparison. This means that version +# numbers behave in a predictable and obvious way, but a way that might +# not necessarily be how people *want* version numbers to behave. There +# wouldn't be a problem if people could stick to purely numeric version +# numbers: just split on period and compare the numbers as tuples. +# However, people insist on putting letters into their version numbers; +# the most common purpose seems to be: +# - indicating a "pre-release" version +# ('alpha', 'beta', 'a', 'b', 'pre', 'p') +# - indicating a post-release patch ('p', 'pl', 'patch') +# but of course this can't cover all version number schemes, and there's +# no way to know what a programmer means without asking him. +# +# The problem is what to do with letters (and other non-numeric +# characters) in a version number. The current implementation does the +# obvious and predictable thing: keep them as strings and compare +# lexically within a tuple comparison. This has the desired effect if +# an appended letter sequence implies something "post-release": +# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". +# +# However, if letters in a version number imply a pre-release version, +# the "obvious" thing isn't correct. Eg. you would expect that +# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison +# implemented here, this just isn't so. +# +# Two possible solutions come to mind. The first is to tie the +# comparison algorithm to a particular set of semantic rules, as has +# been done in the StrictVersion class above. This works great as long +# as everyone can go along with bondage and discipline. Hopefully a +# (large) subset of Python module programmers will agree that the +# particular flavour of bondage and discipline provided by StrictVersion +# provides enough benefit to be worth using, and will submit their +# version numbering scheme to its domination. The free-thinking +# anarchists in the lot will never give in, though, and something needs +# to be done to accommodate them. +# +# Perhaps a "moderately strict" version class could be implemented that +# lets almost anything slide (syntactically), and makes some heuristic +# assumptions about non-digits in version number strings. This could +# sink into special-case-hell, though; if I was as talented and +# idiosyncratic as Larry Wall, I'd go ahead and implement a class that +# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is +# just as happy dealing with things like "2g6" and "1.13++". I don't +# think I'm smart enough to do it right though. +# +# In any case, I've coded the test suite for this module (see +# ../test/test_version.py) specifically to fail on things like comparing +# "1.2a2" and "1.2". That's not because the *code* is doing anything +# wrong, it's because the simple, obvious design doesn't match my +# complicated, hairy expectations for real-world version numbers. It +# would be a snap to fix the test suite to say, "Yep, LooseVersion does +# the Right Thing" (ie. the code matches the conception). But I'd rather +# have a conception that matches common notions about version numbers. + + +class LooseVersion(Version): + """Version numbering for anarchists and software realists. + Implements the standard interface for version number classes as + described above. A version number consists of a series of numbers, + separated by either periods or strings of letters. When comparing + version numbers, the numeric components will be compared + numerically, and the alphabetic components lexically. The following + are all valid version numbers, in no particular order: + + 1.5.1 + 1.5.2b2 + 161 + 3.10a + 8.02 + 3.4j + 1996.07.12 + 3.2.pl0 + 3.1.1.6 + 2g6 + 11g + 0.960923 + 2.2beta29 + 1.13++ + 5.5.kw + 2.0b1pl0 + + In fact, there is no such thing as an invalid version number under + this scheme; the rules for comparison are simple and predictable, + but may not always give the results you want (for some definition + of "want"). + """ + + component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) + + def __init__(self, vstring=None): + if vstring: + self.parse(vstring) + + def parse(self, vstring): + # I've given up on thinking I can reconstruct the version string + # from the parsed tuple -- so I just store the string here for + # use by __str__ + self.vstring = vstring + components = [x for x in self.component_re.split(vstring) if x and x != '.'] + for i, obj in enumerate(components): + try: + components[i] = int(obj) + except ValueError: + pass + + self.version = components + + def __str__(self): + return self.vstring + + def __repr__(self): + return "LooseVersion ('%s')" % str(self) + + def _cmp(self, other): + if isinstance(other, str): + other = LooseVersion(other) + elif not isinstance(other, LooseVersion): + return NotImplemented + + if self.version == other.version: + return 0 + if self.version < other.version: + return -1 + if self.version > other.version: + return 1 + +# end class LooseVersion diff --git a/plugins/module_utils/implementations/mariadb/replication.py b/plugins/module_utils/implementations/mariadb/replication.py index 7968e92..cee4967 100644 --- a/plugins/module_utils/implementations/mariadb/replication.py +++ b/plugins/module_utils/implementations/mariadb/replication.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version -from distutils.version import LooseVersion +from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion def uses_replica_terminology(cursor): diff --git a/plugins/module_utils/implementations/mariadb/user.py b/plugins/module_utils/implementations/mariadb/user.py index fa2cac6..7579157 100644 --- a/plugins/module_utils/implementations/mariadb/user.py +++ b/plugins/module_utils/implementations/mariadb/user.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from distutils.version import LooseVersion +from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version diff --git a/plugins/module_utils/implementations/mysql/replication.py b/plugins/module_utils/implementations/mysql/replication.py index 2fd3d6c..c5324da 100644 --- a/plugins/module_utils/implementations/mysql/replication.py +++ b/plugins/module_utils/implementations/mysql/replication.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version -from distutils.version import LooseVersion +from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion def uses_replica_terminology(cursor): diff --git a/plugins/module_utils/implementations/mysql/user.py b/plugins/module_utils/implementations/mysql/user.py index ce7f5b8..43e400b 100644 --- a/plugins/module_utils/implementations/mysql/user.py +++ b/plugins/module_utils/implementations/mysql/user.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -from distutils.version import LooseVersion +from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version diff --git a/plugins/module_utils/version.py b/plugins/module_utils/version.py new file mode 100644 index 0000000..359cceb --- /dev/null +++ b/plugins/module_utils/version.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2021, Felix Fontein +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +"""Provide version object to compare version numbers.""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can +# remove the _version.py file, and replace the following import by +# +# from ansible.module_utils.compat.version import LooseVersion + +from ._version import LooseVersion diff --git a/plugins/modules/mysql_replication.py b/plugins/modules/mysql_replication.py index f46721a..981074f 100644 --- a/plugins/modules/mysql_replication.py +++ b/plugins/modules/mysql_replication.py @@ -272,7 +272,7 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import ( mysql_common_argument_spec, ) from ansible.module_utils._text import to_native -from distutils.version import LooseVersion +from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion executed_queries = [] diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt new file mode 100644 index 0000000..c0323af --- /dev/null +++ b/tests/sanity/ignore-2.13.txt @@ -0,0 +1,8 @@ +plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen +plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_user.py validate-modules:undocumented-parameter +plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch From f46b84e6702116ad33ebec3da37707b2c2f400ff Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 18 Jan 2022 13:05:37 +0300 Subject: [PATCH 13/63] Release 1.4.4 commit (#277) --- changelogs/CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 14 ++++++++++++++ .../267-prepare_for_distutils_be_removed.yml | 2 -- galaxy.yml | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/267-prepare_for_distutils_be_removed.yml diff --git a/changelogs/CHANGELOG.rst b/changelogs/CHANGELOG.rst index 2a7001c..a72cb86 100644 --- a/changelogs/CHANGELOG.rst +++ b/changelogs/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.4 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.3. + +Bugfixes +-------- + +- Collection core functions - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269). + v1.4.3 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 3d7605a..04953bb 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -304,3 +304,17 @@ releases: - 1.4.3.yml - 205-mysql_info_fix_failure_when_no_tables_in_db.yml release_date: '2021-09-23' + 1.4.4: + changes: + bugfixes: + - Collection core functions - use vendored version of ``distutils.version`` + instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269). + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.3.' + fragments: + - 1.4.4.yml + - 267-prepare_for_distutils_be_removed.yml + release_date: '2022-01-18' diff --git a/changelogs/fragments/267-prepare_for_distutils_be_removed.yml b/changelogs/fragments/267-prepare_for_distutils_be_removed.yml deleted file mode 100644 index 190b178..0000000 --- a/changelogs/fragments/267-prepare_for_distutils_be_removed.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- Collection core functions - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269). diff --git a/galaxy.yml b/galaxy.yml index 3c7a553..fda590c 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.3 +version: 1.4.4 readme: README.md authors: - Ansible community From 96a255c00ab989f30b89b6e38cb108ad09d05c74 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Mon, 14 Mar 2022 13:51:54 +0300 Subject: [PATCH 14/63] [stable-1] Enable and fix integration tests for devel (#298) * Enable and fix integration tests for devel * Add exclusions --- .github/workflows/ansible-test-plugins.yml | 13 ++++++++++++- .../targets/setup_mysql/defaults/main.yml | 2 +- tests/integration/targets/setup_mysql/vars/main.yml | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index da79c04..ea8b4a0 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -61,7 +61,8 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 - #- devel + - stable-2.12 + - devel python: - 3.6 connector: @@ -71,6 +72,16 @@ jobs: exclude: - mysql: 8.0.22 connector: pymysql==0.7.10 + - python: 3.8 + ansible: stable-2.9 + - python: 3.8 + ansible: stable-2.10 + - python: 3.8 + ansible: stable-2.11 + - python: 3.6 + ansible: stable-2.12 + - python: 3.6 + ansible: devel steps: - name: Check out code diff --git a/tests/integration/targets/setup_mysql/defaults/main.yml b/tests/integration/targets/setup_mysql/defaults/main.yml index 7bcb2d2..2908c17 100644 --- a/tests/integration/targets/setup_mysql/defaults/main.yml +++ b/tests/integration/targets/setup_mysql/defaults/main.yml @@ -1,4 +1,4 @@ -dbdeployer_version: 1.52.0 +dbdeployer_version: 1.64.0 dbdeployer_home_dir: /opt/dbdeployer home_dir: /root diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml index e267307..4448ac0 100644 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ b/tests/integration/targets/setup_mysql/vars/main.yml @@ -19,6 +19,7 @@ python_packages: [pymysql == 0.9.3] install_prereqs: - libaio1 - libnuma1 + - libncurses5 install_python_prereqs: - python3-dev From b0de252ce20db171a77198ee038826d29c1bff4c Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 15 Mar 2022 15:53:20 +0300 Subject: [PATCH 15/63] Update requirements (#302) --- README.md | 13 +++++++++++++ plugins/doc_fragments/mysql.py | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d1cee9f..5c44186 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,19 @@ Every voice is important and every idea is valuable. If you have something on yo - 2.11 - devel +### Databases + +- mysql 5.7.31 +- mysql 8.0.22 +- mariadb 10.3.34 +- mariadb 10.5.9 + +### Database connectors + +- pymysql 0.7.10 +- pymysql 0.9.3 +- mysqlclient 2.0.1 + ## External requirements The MySQL modules rely on a MySQL connector. The list of supported drivers is below: diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index b7a9152..9cc5bce 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -71,7 +71,8 @@ options: type: bool version_added: '1.1.0' requirements: - - PyMySQL (Python 2.7 and Python 3.X), or + - mysqlclient (Python 3.5+) or + - PyMySQL (Python 2.7 and Python 3.x) or - MySQLdb (Python 2.x) notes: - Requires the PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) package installed on the remote host. From 59d411ac82704630a89e34a587fd23ab851f73d2 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 15 Mar 2022 17:43:09 +0300 Subject: [PATCH 16/63] Add IF EXISTS clause to DROP USER statement (#309) --- .../fragments/307-mysql_user_add_if_exists_to_drop.yml | 2 ++ plugins/modules/mysql_user.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml diff --git a/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml b/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml new file mode 100644 index 0000000..8de1b17 --- /dev/null +++ b/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml @@ -0,0 +1,2 @@ +bugfixes: +- "mysql_user - fix the possibility for a race condition that breaks certain (circular) replication configurations when ``DROP USER`` is executed on multiple nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin: no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287)." diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 0bea295..91ac370 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -704,7 +704,10 @@ def user_delete(cursor, user, host, host_all, check_mode): hostnames = [host] for hostname in hostnames: - cursor.execute("DROP USER %s@%s", (user, hostname)) + try: + cursor.execute("DROP USER IF EXISTS %s@%s", (user, hostname)) + except Exception: + cursor.execute("DROP USER %s@%s", (user, hostname)) return True From 15ee80b57c8080ece8e5fb85c8b026bff60ad345 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:19:01 +0100 Subject: [PATCH 17/63] Setup patchback bot config file (resolves #310) (#311) (#313) (cherry picked from commit 55458f5b0b40f7e1810b62f24ba27b972cf2ff1a) Co-authored-by: R.Sicart --- .github/patchback.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/patchback.yml diff --git a/.github/patchback.yml b/.github/patchback.yml new file mode 100644 index 0000000..33ad6e8 --- /dev/null +++ b/.github/patchback.yml @@ -0,0 +1,5 @@ +--- +backport_branch_prefix: patchback/backports/ +backport_label_prefix: backport- +target_branch_prefix: stable- +... From bfcf89073ac6fe2c6bd7d28577ac57faee0c3659 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 24 Mar 2022 06:55:08 +0100 Subject: [PATCH 18/63] Fix roles CI (#316) (#318) (cherry picked from commit e6e661b87f182f4a9486a19594b640388b0d6d8f) Co-authored-by: Andrew Klychkov --- .github/workflows/ansible-test-roles.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index 0bc32f6..4f85d26 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -24,13 +24,24 @@ jobs: - 2.0.12 ansible: - stable-2.9 - ### it looks like there's errors for 2.10+ with ansible-lint (https://github.com/ansible/ansible-lint/pull/878) - ### and molecule (_maybe_ relating to https://github.com/ansible-community/molecule/pull/2547) - # - stable-2.10 - # - devel + - stable-2.10 + - stable-2.11 + - stable-2.12 + - devel python: - - 2.7 + - 3.6 - 3.8 + exclude: + - python: 3.8 + ansible: stable-2.9 + - python: 3.8 + ansible: stable-2.10 + - python: 3.8 + ansible: stable-2.11 + - python: 3.6 + ansible: stable-2.12 + - python: 3.6 + ansible: devel steps: @@ -44,7 +55,7 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install ansible-base (${{ matrix.ansible }}) + - name: Install ansible-core (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - name: Install molecule and related dependencies From d5a1e3639a09170cc1f450a57f3fde69898f0511 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 25 Mar 2022 12:33:01 +0100 Subject: [PATCH 19/63] mysql_user: clarify behavior of priv parameter (#319) (#320) (cherry picked from commit 5afae459dc35b4507d25a34d7cc901231a3d07f4) Co-authored-by: Andrew Klychkov --- plugins/modules/mysql_user.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 91ac370..58bb168 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -45,7 +45,7 @@ options: description: - "MySQL privileges string in the format: C(db.table:priv1,priv2)." - "Multiple privileges can be specified by separating each one using - a forward slash: C(db.table:priv/db.table:priv)." + a forward slash: C(db.table1:priv/db.table2:priv)." - The format is based on MySQL C(GRANT) statement. - Database and table names can be quoted, MySQL-style. - If column privileges are used, the C(priv1,priv2) part must be @@ -54,6 +54,11 @@ options: by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))). - Can be passed as a dictionary (see the examples). - Supports GRANTs for procedures and functions (see the examples). + - "Note: If you pass the same C(db.table) combination to this parameter + two or more times with different privileges, + for example, C('*.*:SELECT/*.*:SHOW VIEW'), only the last one will be applied, + in this example, it will be C(SHOW VIEW) respectively. + Use C('*.*:SELECT,SHOW VIEW') instead to apply both." type: raw append_privs: description: From 278337d34fbd51d3ddcd4eec67661828969a4152 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Sat, 2 Apr 2022 18:33:52 +0300 Subject: [PATCH 20/63] [stable-1] Backports (#325) * Clarified error message about missing python modules (#279) * Clarified error message about missing python modules, and tweak documentation to suggest overriding interpreter. * Mention mysqlclient as another option * Correct mysqlclient suggestions from python2 to python3 Co-authored-by: Matthew Exon (cherry picked from commit 82baf7508ce757b102e229b51f902c46cf18bebc) * Copy ignore-2.13.txt to ignore-2.14.txt (#323) * Copy ignore-2.13.txt to ignore-2.14.txt * Fix sanity (cherry picked from commit c16b2428e80f8f837469d41fca48f6b0015fab8f) Co-authored-by: Matthew Exon --- plugins/doc_fragments/mysql.py | 11 +++++++---- plugins/module_utils/mysql.py | 5 ++++- tests/sanity/ignore-2.14.txt | 8 ++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 tests/sanity/ignore-2.14.txt diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index 9cc5bce..4b531d4 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -79,10 +79,13 @@ notes: The Python package may be installed with apt-get install python-pymysql (Ubuntu; see M(ansible.builtin.apt)) or yum install python2-PyMySQL (RHEL/CentOS/Fedora; see M(ansible.builtin.yum)). You can also use dnf install python2-PyMySQL for newer versions of Fedora; see M(ansible.builtin.dnf). - - Be sure you have PyMySQL or MySQLdb library installed on the target machine - for the Python interpreter Ansible uses, for example, if it is Python 3, - you must install the library for Python 3. You can also change the interpreter. - For more information, see U(https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html). + - Be sure you have mysqlclient, PyMySQL, or MySQLdb library installed on the target machine + for the Python interpreter Ansible discovers. For example if ansible discovers and uses Python 3, you need to install + the Python 3 version of PyMySQL or mysqlclient. If ansible discovers and uses Python 2, you need to install the Python 2 + version of either PyMySQL or MySQL-python. + - If you have trouble, it may help to force Ansible to use the Python interpreter you need by specifying + C(ansible_python_interpreter). For more information, see + U(https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html). - Both C(login_password) and C(login_user) are required when you are passing credentials. If none are present, the module will attempt to read the credentials from C(~/.my.cnf), and finally fall back to using the MySQL diff --git a/plugins/module_utils/mysql.py b/plugins/module_utils/mysql.py index 5af9c20..9492ea8 100644 --- a/plugins/module_utils/mysql.py +++ b/plugins/module_utils/mysql.py @@ -29,7 +29,10 @@ except ImportError: except ImportError: mysql_driver = None -mysql_driver_fail_msg = 'The PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) module is required.' +mysql_driver_fail_msg = ('A MySQL module is required: for Python 2.7 either PyMySQL, or ' + 'MySQL-python, or for Python 3.X mysqlclient or PyMySQL. ' + 'Consider setting ansible_python_interpreter to use ' + 'the intended Python version.') def parse_from_mysql_config_file(cnf): diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt new file mode 100644 index 0000000..c0323af --- /dev/null +++ b/tests/sanity/ignore-2.14.txt @@ -0,0 +1,8 @@ +plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen +plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_user.py validate-modules:undocumented-parameter +plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch From 2a57a4d6591311ce28fc391cbd58da3ff3ef6807 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Sun, 3 Apr 2022 09:10:42 +0300 Subject: [PATCH 21/63] CI: add testing against ansible-core 2.13 (#328) Co-authored-by: R.Sicart --- .github/workflows/ansible-test-plugins.yml | 7 +++++++ .github/workflows/ansible-test-roles.yml | 3 +++ README.md | 2 ++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index ea8b4a0..7321a61 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -28,6 +28,8 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 + - stable-2.12 + - stable-2.13 - devel steps: @@ -62,6 +64,7 @@ jobs: - stable-2.10 - stable-2.11 - stable-2.12 + - stable-2.13 - devel python: - 3.6 @@ -80,6 +83,8 @@ jobs: ansible: stable-2.11 - python: 3.6 ansible: stable-2.12 + - python: 3.6 + ansible: stable-2.13 - python: 3.6 ansible: devel steps: @@ -127,6 +132,8 @@ jobs: - stable-2.9 - stable-2.10 - stable-2.11 + - stable-2.12 + - stable-2.13 - devel steps: diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index 4f85d26..5c27416 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -27,6 +27,7 @@ jobs: - stable-2.10 - stable-2.11 - stable-2.12 + - stable-2.13 - devel python: - 3.6 @@ -40,6 +41,8 @@ jobs: ansible: stable-2.11 - python: 3.6 ansible: stable-2.12 + - python: 3.6 + ansible: stable-2.13 - python: 3.6 ansible: devel diff --git a/README.md b/README.md index 5c44186..9856c36 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ Every voice is important and every idea is valuable. If you have something on yo - 2.9 - 2.10 - 2.11 +- 2.12 +- 2.13 - devel ### Databases From b730cd6675722fd0829701bf3f6351a9aa0957bb Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 29 Apr 2022 18:52:07 +0300 Subject: [PATCH 22/63] mysql_user: added flush privileges to write dynamic privs into db (#340) --- changelogs/fragments/338-mysql_user_fix.yml | 2 ++ plugins/modules/mysql_user.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/338-mysql_user_fix.yml diff --git a/changelogs/fragments/338-mysql_user_fix.yml b/changelogs/fragments/338-mysql_user_fix.yml new file mode 100644 index 0000000..89b9dc8 --- /dev/null +++ b/changelogs/fragments/338-mysql_user_fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - "mysql_user - fix missing dynamic privileges after revoke and grant privileges to user (https://github.com/ansible-collections/community.mysql/issues/120)." diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 58bb168..89cbdd8 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -952,6 +952,7 @@ def privileges_revoke(cursor, user, host, db_table, priv, grant_option): query.append("FROM %s@%s") query = ' '.join(query) cursor.execute(query, (user, host)) + cursor.execute("FLUSH PRIVILEGES") def privileges_grant(cursor, user, host, db_table, priv, tls_requires): From a2a4a1ff61b6f7a3f00d046350e9161ad6c72718 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 12 May 2022 11:53:46 +0200 Subject: [PATCH 23/63] Move CHANGELOG.rst at top level (#349) (#351) (cherry picked from commit f57ed38beb46f25aeb37eb33cdce262f8f5ed5b1) Co-authored-by: Andrew Klychkov --- changelogs/CHANGELOG.rst => CHANGELOG.rst | 0 changelogs/config.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename changelogs/CHANGELOG.rst => CHANGELOG.rst (100%) diff --git a/changelogs/CHANGELOG.rst b/CHANGELOG.rst similarity index 100% rename from changelogs/CHANGELOG.rst rename to CHANGELOG.rst diff --git a/changelogs/config.yaml b/changelogs/config.yaml index 559e6c4..70ab036 100644 --- a/changelogs/config.yaml +++ b/changelogs/config.yaml @@ -1,4 +1,4 @@ -changelog_filename_template: CHANGELOG.rst +changelog_filename_template: ../CHANGELOG.rst changelog_filename_version_depth: 0 changes_file: changelog.yaml changes_format: combined From 256817ca32d88ade69d139ea139b33c0debf502b Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 12 May 2022 15:11:36 +0300 Subject: [PATCH 24/63] Drop support for Ansible 2.9 and ansible-base 2.10 (#347) --- .github/workflows/ansible-test-plugins.yml | 10 ---------- .github/workflows/ansible-test-roles.yml | 6 ------ README.md | 8 ++++---- changelogs/fragments/drop_support_of_2.9-2.10.yml | 2 ++ plugins/module_utils/version.py | 2 +- 5 files changed, 7 insertions(+), 21 deletions(-) create mode 100644 changelogs/fragments/drop_support_of_2.9-2.10.yml diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 7321a61..cf2b864 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -25,8 +25,6 @@ jobs: strategy: matrix: ansible: - - stable-2.9 - - stable-2.10 - stable-2.11 - stable-2.12 - stable-2.13 @@ -60,8 +58,6 @@ jobs: - 5.7.31 - 8.0.22 ansible: - - stable-2.9 - - stable-2.10 - stable-2.11 - stable-2.12 - stable-2.13 @@ -75,10 +71,6 @@ jobs: exclude: - mysql: 8.0.22 connector: pymysql==0.7.10 - - python: 3.8 - ansible: stable-2.9 - - python: 3.8 - ansible: stable-2.10 - python: 3.8 ansible: stable-2.11 - python: 3.6 @@ -129,8 +121,6 @@ jobs: fail-fast: true matrix: ansible: - - stable-2.9 - - stable-2.10 - stable-2.11 - stable-2.12 - stable-2.13 diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index 5c27416..bda6986 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -23,8 +23,6 @@ jobs: mysql: - 2.0.12 ansible: - - stable-2.9 - - stable-2.10 - stable-2.11 - stable-2.12 - stable-2.13 @@ -33,10 +31,6 @@ jobs: - 3.6 - 3.8 exclude: - - python: 3.8 - ansible: stable-2.9 - - python: 3.8 - ansible: stable-2.10 - python: 3.8 ansible: stable-2.11 - python: 3.6 diff --git a/README.md b/README.md index 9856c36..3be68b4 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,14 @@ Every voice is important and every idea is valuable. If you have something on yo - [mysql_user](https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_user_module.html) - [mysql_variables](https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_variables_module.html) -## Tested with Ansible +## Tested with + +### ansible-core -- 2.9 -- 2.10 - 2.11 - 2.12 - 2.13 -- devel +- current development version ### Databases diff --git a/changelogs/fragments/drop_support_of_2.9-2.10.yml b/changelogs/fragments/drop_support_of_2.9-2.10.yml new file mode 100644 index 0000000..8570210 --- /dev/null +++ b/changelogs/fragments/drop_support_of_2.9-2.10.yml @@ -0,0 +1,2 @@ +major_changes: +- The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base 2.10``. While we take no active measures to prevent usage and there are no plans to introduce incompatible code to the modules, we will stop testing against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be End of Life and if you are still using them, you should consider upgrading to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible (https://github.com/ansible-collections/community.mysql/pull/343). diff --git a/plugins/module_utils/version.py b/plugins/module_utils/version.py index 359cceb..9473134 100644 --- a/plugins/module_utils/version.py +++ b/plugins/module_utils/version.py @@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can +# Once we drop support for ansible-core 2.11, we can # remove the _version.py file, and replace the following import by # # from ansible.module_utils.compat.version import LooseVersion From 393023eb071a3e4bcf062da311ecca3c72bc30c4 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 12 May 2022 16:19:20 +0300 Subject: [PATCH 25/63] [stable-1] mysql_user: fix parsing privs when a user has roles assigned to it (#346) * mysql_user: fix parsing privs when a user has roles assigned to it * Fix CI * Fix CI --- .gitignore | 1 + ...ser_fix_pars_users_with_roles_assigned.yml | 2 + plugins/modules/mysql_user.py | 11 +++ .../targets/test_mysql_user/tasks/main.yml | 3 + .../test_user_grants_with_roles_applied.yml | 98 +++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml diff --git a/.gitignore b/.gitignore index f440722..6bbe85a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /tests/output/ /changelogs/.plugin-cache.yaml +*.swp # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml b/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml new file mode 100644 index 0000000..121bc46 --- /dev/null +++ b/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml @@ -0,0 +1,2 @@ +bugfixes: +- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231). diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 89cbdd8..2fb76fd 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -750,8 +750,19 @@ def privileges_get(cursor, user, host): for grant in grants: res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0]) + if res is None: + # If a user has roles assigned, we'll have one of priv tuples looking like + # GRANT `admin`@`%` TO `user1`@`localhost` + # which will result None as res value. + # As we use the mysql_role module (community.mysql 2.0.0+) to manipulate roles + # we just ignore such privs below: + res = re.match("""GRANT (.+) TO (['`"]).*""", grant[0]) + if res: + continue + raise InvalidPrivsError('unable to parse the MySQL grant string: %s' % grant[0]) + privileges = res.group(1).split(",") privileges = [pick(x.strip()) for x in privileges] diff --git a/tests/integration/targets/test_mysql_user/tasks/main.yml b/tests/integration/targets/test_mysql_user/tasks/main.yml index 93cb12d..9b6caf3 100644 --- a/tests/integration/targets/test_mysql_user/tasks/main.yml +++ b/tests/integration/targets/test_mysql_user/tasks/main.yml @@ -282,3 +282,6 @@ - import_tasks: issue-64560.yaml tags: - issue-64560 + + # https://github.com/ansible-collections/community.mysql/issues/231 + - include: test_user_grants_with_roles_applied.yml diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml new file mode 100644 index 0000000..7af3890 --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml @@ -0,0 +1,98 @@ +# https://github.com/ansible-collections/community.mysql/issues/231 +- vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + + block: + - name: Get server version + mysql_info: + <<: *mysql_params + register: srv + + # Skip unsupported versions + - meta: end_play + when: srv['version']['major'] < 8 + + - name: Create test databases + mysql_db: + <<: *mysql_params + name: '{{ item }}' + state: present + loop: + - data1 + - data2 + + - name: Create user with privileges + mysql_user: + <<: *mysql_params + name: '{{ user_name_3 }}' + password: '{{ user_password_3 }}' + priv: + "data1.*": "SELECT" + "data2.*": "SELECT" + state: present + + - name: Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" + register: result + + - name: Assert user has giving privileges + assert: + that: + - "'GRANT SELECT ON `data1`.*' in result.stdout" + - "'GRANT SELECT ON `data2`.*' in result.stdout" + + - name: Create role + mysql_query: + <<: *mysql_params + query: CREATE ROLE IF NOT EXISTS test231 + + + - name: Grant role + mysql_query: + <<: *mysql_params + query: 'GRANT test231 TO {{ user_name_3 }}@localhost' + + - name: Try to change privs + mysql_user: + <<: *mysql_params + name: '{{ user_name_3 }}' + priv: + "data1.*": "INSERT" + "data2.*": "INSERT" + state: present + + - name: Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" + register: result + + - name: Assert user has giving privileges + assert: + that: + - "'GRANT INSERT ON `data1`.*' in result.stdout" + - "'GRANT INSERT ON `data2`.*' in result.stdout" + + ########## + # Clean up + - name: Drop test databases + mysql_db: + <<: *mysql_params + name: '{{ item }}' + state: present + loop: + - data1 + - data2 + + - name: Drop test user + mysql_user: + <<: *mysql_params + name: '{{ user_name_3 }}' + state: absent + + - name: Drop test role + mysql_query: + <<: *mysql_params + query: DROP ROLE IF EXISTS test231 From 3bb7b00497d5fd584f10037a8818b4023e96c4f0 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 13 May 2022 10:07:25 +0300 Subject: [PATCH 26/63] Release 1.4.5 commit (#353) --- CHANGELOG.rst | 22 ++++++++++++++ changelogs/changelog.yaml | 30 +++++++++++++++++++ ...ser_fix_pars_users_with_roles_assigned.yml | 2 -- .../307-mysql_user_add_if_exists_to_drop.yml | 2 -- changelogs/fragments/338-mysql_user_fix.yml | 2 -- .../fragments/drop_support_of_2.9-2.10.yml | 2 -- galaxy.yml | 2 +- 7 files changed, 53 insertions(+), 9 deletions(-) delete mode 100644 changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml delete mode 100644 changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml delete mode 100644 changelogs/fragments/338-mysql_user_fix.yml delete mode 100644 changelogs/fragments/drop_support_of_2.9-2.10.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a72cb86..e820f30 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,28 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.5 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.4. + +Major Changes +------------- + +- The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base 2.10``. While we take no active measures to prevent usage and there are no plans to introduce incompatible code to the modules, we will stop testing against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be End of Life and if you are still using them, you should consider upgrading to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible (https://github.com/ansible-collections/community.mysql/pull/343). + +Bugfixes +-------- + +- mysql_user - fix missing dynamic privileges after revoke and grant privileges to user (https://github.com/ansible-collections/community.mysql/issues/120). +- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231). +- mysql_user - fix the possibility for a race condition that breaks certain (circular) replication configurations when ``DROP USER`` is executed on multiple nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin: no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287). + v1.4.4 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 04953bb..d965af2 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -318,3 +318,33 @@ releases: - 1.4.4.yml - 267-prepare_for_distutils_be_removed.yml release_date: '2022-01-18' + 1.4.5: + changes: + bugfixes: + - mysql_user - fix missing dynamic privileges after revoke and grant privileges + to user (https://github.com/ansible-collections/community.mysql/issues/120). + - mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231). + - 'mysql_user - fix the possibility for a race condition that breaks certain + (circular) replication configurations when ``DROP USER`` is executed on multiple + nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin: + no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287).' + major_changes: + - The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base + 2.10``. While we take no active measures to prevent usage and there are no + plans to introduce incompatible code to the modules, we will stop testing + against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be + End of Life and if you are still using them, you should consider upgrading + to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible + (https://github.com/ansible-collections/community.mysql/pull/343). + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.4.' + fragments: + - 001-mysql_user_fix_pars_users_with_roles_assigned.yml + - 1.4.5.yml + - 307-mysql_user_add_if_exists_to_drop.yml + - 338-mysql_user_fix.yml + - drop_support_of_2.9-2.10.yml + release_date: '2022-05-13' diff --git a/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml b/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml deleted file mode 100644 index 121bc46..0000000 --- a/changelogs/fragments/001-mysql_user_fix_pars_users_with_roles_assigned.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231). diff --git a/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml b/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml deleted file mode 100644 index 8de1b17..0000000 --- a/changelogs/fragments/307-mysql_user_add_if_exists_to_drop.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- "mysql_user - fix the possibility for a race condition that breaks certain (circular) replication configurations when ``DROP USER`` is executed on multiple nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin: no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287)." diff --git a/changelogs/fragments/338-mysql_user_fix.yml b/changelogs/fragments/338-mysql_user_fix.yml deleted file mode 100644 index 89b9dc8..0000000 --- a/changelogs/fragments/338-mysql_user_fix.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "mysql_user - fix missing dynamic privileges after revoke and grant privileges to user (https://github.com/ansible-collections/community.mysql/issues/120)." diff --git a/changelogs/fragments/drop_support_of_2.9-2.10.yml b/changelogs/fragments/drop_support_of_2.9-2.10.yml deleted file mode 100644 index 8570210..0000000 --- a/changelogs/fragments/drop_support_of_2.9-2.10.yml +++ /dev/null @@ -1,2 +0,0 @@ -major_changes: -- The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base 2.10``. While we take no active measures to prevent usage and there are no plans to introduce incompatible code to the modules, we will stop testing against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be End of Life and if you are still using them, you should consider upgrading to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible (https://github.com/ansible-collections/community.mysql/pull/343). diff --git a/galaxy.yml b/galaxy.yml index fda590c..9a89aac 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.4 +version: 1.4.5 readme: README.md authors: - Ansible community From f4736770e39b70908e4452309e6fc4e257a8c664 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 17 May 2022 08:24:07 +0200 Subject: [PATCH 27/63] Add PSF-license.txt file (#356) (#359) * Add PSF-license.txt file. * Update with actual CPython 3.9.5 license. (cherry picked from commit b2e476cb1a5b1723238e75e7c674a7abd540d75f) --- PSF-license.txt | 48 ++++++++++++++++++++++++++++ changelogs/fragments/psf-license.yml | 2 ++ plugins/module_utils/_version.py | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 PSF-license.txt create mode 100644 changelogs/fragments/psf-license.yml diff --git a/PSF-license.txt b/PSF-license.txt new file mode 100644 index 0000000..35acd7f --- /dev/null +++ b/PSF-license.txt @@ -0,0 +1,48 @@ +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/changelogs/fragments/psf-license.yml b/changelogs/fragments/psf-license.yml new file mode 100644 index 0000000..f8fbc0b --- /dev/null +++ b/changelogs/fragments/psf-license.yml @@ -0,0 +1,2 @@ +bugfixes: + - Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``. diff --git a/plugins/module_utils/_version.py b/plugins/module_utils/_version.py index 59ee9db..ce02717 100644 --- a/plugins/module_utils/_version.py +++ b/plugins/module_utils/_version.py @@ -3,7 +3,7 @@ # Implements multiple version numbering conventions for the # Python Module Distribution Utilities. # -# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0) +# PSF License (see PSF-license.txt or https://opensource.org/licenses/Python-2.0) # """Provides classes to represent module version numbers (one class for From 0921d4eef5f35f16fad6927115e64afa5f0c81a0 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 17 May 2022 13:08:28 +0300 Subject: [PATCH 28/63] Release 1.4.6 commit (#361) --- CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 13 +++++++++++++ changelogs/fragments/psf-license.yml | 2 -- galaxy.yml | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/psf-license.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e820f30..2c7e12f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.6 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.5. + +Bugfixes +-------- + +- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``. + v1.4.5 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index d965af2..0b8b970 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -348,3 +348,16 @@ releases: - 338-mysql_user_fix.yml - drop_support_of_2.9-2.10.yml release_date: '2022-05-13' + 1.4.6: + changes: + bugfixes: + - Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``. + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.5.' + fragments: + - 1.4.6.yml + - psf-license.yml + release_date: '2022-05-17' diff --git a/changelogs/fragments/psf-license.yml b/changelogs/fragments/psf-license.yml deleted file mode 100644 index f8fbc0b..0000000 --- a/changelogs/fragments/psf-license.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``. diff --git a/galaxy.yml b/galaxy.yml index 9a89aac..278ecbd 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.5 +version: 1.4.6 readme: README.md authors: - Ansible community From f7677aa05bc52e354e4f5f5d834169721f58a02f Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 26 May 2022 09:41:21 +0300 Subject: [PATCH 29/63] [stable-1] mysql_query: fix false change reports when IF NOT EXISTS clause is used (#375) * mysql_query: fix false change reports when IF NOT EXISTS clause is used (#322) * mysql_query: fix false change reports when IF NOT EXISTS clause is used * Fix * Fix doc, add fragment * Improve doc (cherry picked from commit 647461010db5af4fb68164eeacbfda3dce6a41c8) * Fix tests --- ...22-mysql_query_fix_false_change_report.yml | 2 ++ plugins/modules/mysql_query.py | 32 +++++++++++++++--- .../targets/setup_mysql/tasks/install.yml | 17 ++++++++++ .../tasks/mysql_query_initial.yml | 33 +++++++++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/322-mysql_query_fix_false_change_report.yml diff --git a/changelogs/fragments/322-mysql_query_fix_false_change_report.yml b/changelogs/fragments/322-mysql_query_fix_false_change_report.yml new file mode 100644 index 0000000..db53922 --- /dev/null +++ b/changelogs/fragments/322-mysql_query_fix_false_change_report.yml @@ -0,0 +1,2 @@ +bugfixes: +- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause is used (https://github.com/ansible-collections/community.mysql/issues/268). diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index fc789c5..a91335b 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -22,6 +22,10 @@ options: description: - SQL query to run. Multiple queries can be passed using YAML list syntax. - Must be a string or YAML list containing strings. + - Note that if you use the C(IF EXISTS/IF NOT EXISTS) clauses in your query + and C(mysqlclient) connector, the module will report that + the state has been changed even if it has not. If it is important in your + workflow, use the C(PyMySQL) connector instead. type: raw required: yes positional_args: @@ -103,6 +107,8 @@ rowcount: sample: [5, 1] ''' +import warnings + from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.mysql.plugins.module_utils.mysql import ( mysql_connect, @@ -196,9 +202,22 @@ def main(): executed_queries = [] rowcount = [] + already_exists = False for q in query: try: - cursor.execute(q, arguments) + with warnings.catch_warnings(): + warnings.filterwarnings(action='error', + message='.*already exists*', + category=mysql_driver.Warning) + + try: + cursor.execute(q, arguments) + except mysql_driver.Warning: + # When something is run with IF NOT EXISTS + # and there's "already exists" MySQL warning, + # set the flag as True. + # PyMySQL throws the warning, mysqlclinet does NOT. + already_exists = True except Exception as e: if not autocommit: @@ -208,7 +227,8 @@ def main(): module.fail_json(msg="Cannot execute SQL '%s' args [%s]: %s" % (q, arguments, to_native(e))) try: - query_result.append([dict(row) for row in cursor.fetchall()]) + if not already_exists: + query_result.append([dict(row) for row in cursor.fetchall()]) except Exception as e: if not autocommit: @@ -224,8 +244,12 @@ def main(): for keyword in DDL_QUERY_KEYWORDS: if keyword in q: - changed = True - + if already_exists: + # Indicates the entity already exists + changed = False + already_exists = False # Reset flag + else: + changed = True try: executed_queries.append(cursor._last_executed) except AttributeError: diff --git a/tests/integration/targets/setup_mysql/tasks/install.yml b/tests/integration/targets/setup_mysql/tasks/install.yml index aacdddc..57e4b31 100644 --- a/tests/integration/targets/setup_mysql/tasks/install.yml +++ b/tests/integration/targets/setup_mysql/tasks/install.yml @@ -28,6 +28,23 @@ - name: "{{ role_name }} | install | install python packages" pip: name: "{{ python_packages }}" + register: connector + +- name: Extract connector.name.0 content + set_fact: + connector_name: "{{ connector.name.0 }}" + +- name: Debug connector_name content + debug: + msg: '{{ connector_name }}' + +- name: Extract connector version + set_fact: + connector_ver: "{{ connector_name.split('=')[2].strip() }}" + +- name: Debug connector_ver var content + debug: + msg: '{{ connector_ver }}' - name: "{{ role_name }} | install | install packages required by mysql" apt: diff --git a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml index 30182fe..2d971ab 100644 --- a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml +++ b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml @@ -321,6 +321,39 @@ - result is changed - result.rowcount == [2] + # Issue https://github.com/ansible-collections/community.mysql/issues/268 + - name: Create table + mysql_query: + <<: *mysql_params + login_db: '{{ test_db }}' + query: "CREATE TABLE issue268 (id int)" + single_transaction: yes + + # Issue https://github.com/ansible-collections/community.mysql/issues/268 + - name: Create table with IF NOT EXISTS + mysql_query: + <<: *mysql_params + login_db: '{{ test_db }}' + query: "CREATE TABLE IF NOT EXISTS issue268 (id int)" + single_transaction: yes + register: result + + # Issue https://github.com/ansible-collections/community.mysql/issues/268 + - assert: + that: + # PyMySQL driver throws a warning, so the following is correct + - result is not changed + when: connector.name.0 is search('pymysql') + + # Issue https://github.com/ansible-collections/community.mysql/issues/268 + - assert: + that: + # mysqlclient driver throws nothing, so it's impossible to figure out + # if the state was changed or not. + # We assume that it was for DDL queryes by default in the code + - result is changed + when: connector.name.0 is search('mysqlclient') + - name: Drop db {{ test_db }} mysql_query: <<: *mysql_params From 4d4a5f2a02e0a7ef98db5ac82d49cd0859d75726 Mon Sep 17 00:00:00 2001 From: hubiongithub <79990207+hubiongithub@users.noreply.github.com> Date: Tue, 31 May 2022 17:43:15 +0200 Subject: [PATCH 30/63] merge into stable1 (#383) * PR379 merge * Update plugins/modules/mysql_user.py Co-authored-by: Andrew Klychkov Co-authored-by: Andrew Klychkov --- .../fragments/334-mysql_user_fix_logic_on_oncreate.yml | 2 ++ plugins/modules/mysql_user.py | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml diff --git a/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml b/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml new file mode 100644 index 0000000..4ac88a1 --- /dev/null +++ b/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml @@ -0,0 +1,2 @@ +bugfixes: + - "mysql_user - fix logic when ``update_password`` is set to ``on_create`` for users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334). The ``on_create`` sets ``password`` to None for old mysql_native_authentication but not for authentiation methods which uses the ``plugin*`` arguments. This PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``, ``plugin_auth_string`` to None in the list of arguments to change" diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 2fb76fd..1151d92 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -22,7 +22,8 @@ options: required: true password: description: - - Set the user's password. + - Set the user's password. Only for C(mysql_native_password) authentication. + For other authentication plugins see the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string). type: str encrypted: description: @@ -94,8 +95,8 @@ options: default: no update_password: description: - - C(always) will update passwords if they differ. - - C(on_create) will only set the password for newly created users. + - C(always) will update passwords if they differ. This affects I(password) and the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string). + - C(on_create) will only set the password or the combination of plugin, plugin_hash_string, plugin_auth_string for newly created users. type: str choices: [ always, on_create ] default: always @@ -1263,7 +1264,7 @@ def main(): priv, append_privs, tls_requires, module) else: changed, msg = user_mod(cursor, user, host, host_all, None, encrypted, - plugin, plugin_hash_string, plugin_auth_string, + None, None, None, priv, append_privs, tls_requires, module) except (SQLParseError, InvalidPrivsError, mysql_driver.Error) as e: From 89eb2d2feadccfc66aedcfcf7397692a004ecd5b Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 1 Jun 2022 07:58:16 +0200 Subject: [PATCH 31/63] Changed += to append because cmd is a list (#377) (#386) Using += on a list cause some problems druing creation of mysql command: /usr/bin/mysql - - u s e r = r o o t - - p a s s w o r d = ' ' --socket=/run/mysqld/mysqld.sock (cherry picked from commit 2e9d50f27476bb46dea152fb4c1383022ae68860) Co-authored-by: Maciej --- plugins/modules/mysql_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/mysql_db.py b/plugins/modules/mysql_db.py index aa9ade0..52da021 100644 --- a/plugins/modules/mysql_db.py +++ b/plugins/modules/mysql_db.py @@ -442,7 +442,7 @@ def db_import(module, host, user, password, db_name, target, all_databases, port cmd.append("--defaults-extra-file=%s" % shlex_quote(config_file)) if check_implicit_admin: - cmd += " --user=root --password=''" + cmd.append("--user=root --password=''") else: if user: cmd.append("--user=%s" % shlex_quote(user)) From 949cb0c1dd3e11d23368e9ca6b2ee4054ba96186 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 2 Jun 2022 09:15:26 +0300 Subject: [PATCH 32/63] Release 1.4.7 commit (#387) --- CHANGELOG.rst | 16 ++++++++++++++ changelogs/changelog.yaml | 21 +++++++++++++++++++ ...22-mysql_query_fix_false_change_report.yml | 2 -- .../334-mysql_user_fix_logic_on_oncreate.yml | 2 -- galaxy.yml | 2 +- 5 files changed, 38 insertions(+), 5 deletions(-) delete mode 100644 changelogs/fragments/322-mysql_query_fix_false_change_report.yml delete mode 100644 changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2c7e12f..96cfaee 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,22 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.7 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.6. + +Bugfixes +-------- + +- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause is used (https://github.com/ansible-collections/community.mysql/issues/268). +- mysql_user - fix logic when ``update_password`` is set to ``on_create`` for users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334). The ``on_create`` sets ``password`` to None for old mysql_native_authentication but not for authentiation methods which uses the ``plugin*`` arguments. This PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``, ``plugin_auth_string`` to None in the list of arguments to change + v1.4.6 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 0b8b970..cb46074 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -361,3 +361,24 @@ releases: - 1.4.6.yml - psf-license.yml release_date: '2022-05-17' + 1.4.7: + changes: + bugfixes: + - mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause + is used (https://github.com/ansible-collections/community.mysql/issues/268). + - mysql_user - fix logic when ``update_password`` is set to ``on_create`` for + users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334). + The ``on_create`` sets ``password`` to None for old mysql_native_authentication + but not for authentiation methods which uses the ``plugin*`` arguments. This + PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``, + ``plugin_auth_string`` to None in the list of arguments to change + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.6.' + fragments: + - 1.4.7.yml + - 322-mysql_query_fix_false_change_report.yml + - 334-mysql_user_fix_logic_on_oncreate.yml + release_date: '2022-06-02' diff --git a/changelogs/fragments/322-mysql_query_fix_false_change_report.yml b/changelogs/fragments/322-mysql_query_fix_false_change_report.yml deleted file mode 100644 index db53922..0000000 --- a/changelogs/fragments/322-mysql_query_fix_false_change_report.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause is used (https://github.com/ansible-collections/community.mysql/issues/268). diff --git a/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml b/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml deleted file mode 100644 index 4ac88a1..0000000 --- a/changelogs/fragments/334-mysql_user_fix_logic_on_oncreate.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - "mysql_user - fix logic when ``update_password`` is set to ``on_create`` for users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334). The ``on_create`` sets ``password`` to None for old mysql_native_authentication but not for authentiation methods which uses the ``plugin*`` arguments. This PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``, ``plugin_auth_string`` to None in the list of arguments to change" diff --git a/galaxy.yml b/galaxy.yml index 278ecbd..f94c962 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.6 +version: 1.4.7 readme: README.md authors: - Ansible community From d8ab933d793b16f8f64b476bb36e80c651327797 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 3 Jun 2022 17:28:29 +0300 Subject: [PATCH 33/63] Update licensing information (#392) --- changelogs/fragments/simplified-bsd-license.yml | 2 ++ plugins/module_utils/database.py | 2 +- .../module_utils/implementations/mariadb/replication.py | 4 ++++ plugins/module_utils/implementations/mariadb/user.py | 4 ++++ plugins/module_utils/implementations/mysql/replication.py | 4 ++++ plugins/module_utils/implementations/mysql/user.py | 4 ++++ plugins/module_utils/mysql.py | 2 +- simplified_bsd.txt | 8 ++++++++ 8 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/simplified-bsd-license.yml create mode 100644 simplified_bsd.txt diff --git a/changelogs/fragments/simplified-bsd-license.yml b/changelogs/fragments/simplified-bsd-license.yml new file mode 100644 index 0000000..574a695 --- /dev/null +++ b/changelogs/fragments/simplified-bsd-license.yml @@ -0,0 +1,2 @@ +bugfixes: + - Include ``simplified_bsd.txt`` license file for various module utils. diff --git a/plugins/module_utils/database.py b/plugins/module_utils/database.py index 6785030..da0375d 100644 --- a/plugins/module_utils/database.py +++ b/plugins/module_utils/database.py @@ -6,7 +6,7 @@ # # Copyright (c) 2014, Toshio Kuratomi # -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) +# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) from __future__ import (absolute_import, division, print_function) __metaclass__ = type diff --git a/plugins/module_utils/implementations/mariadb/replication.py b/plugins/module_utils/implementations/mariadb/replication.py index cee4967..a1733e7 100644 --- a/plugins/module_utils/implementations/mariadb/replication.py +++ b/plugins/module_utils/implementations/mariadb/replication.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- + +# 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 diff --git a/plugins/module_utils/implementations/mariadb/user.py b/plugins/module_utils/implementations/mariadb/user.py index 7579157..b87ff69 100644 --- a/plugins/module_utils/implementations/mariadb/user.py +++ b/plugins/module_utils/implementations/mariadb/user.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- + +# 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 diff --git a/plugins/module_utils/implementations/mysql/replication.py b/plugins/module_utils/implementations/mysql/replication.py index c5324da..2e50bea 100644 --- a/plugins/module_utils/implementations/mysql/replication.py +++ b/plugins/module_utils/implementations/mysql/replication.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- + +# 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 diff --git a/plugins/module_utils/implementations/mysql/user.py b/plugins/module_utils/implementations/mysql/user.py index 43e400b..b141903 100644 --- a/plugins/module_utils/implementations/mysql/user.py +++ b/plugins/module_utils/implementations/mysql/user.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- + +# 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 diff --git a/plugins/module_utils/mysql.py b/plugins/module_utils/mysql.py index 9492ea8..d256599 100644 --- a/plugins/module_utils/mysql.py +++ b/plugins/module_utils/mysql.py @@ -7,7 +7,7 @@ # Copyright (c), Jonathan Mainguy , 2015 # Most of this was originally added by Sven Schliesing @muffl0n in the mysql_user.py module # -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) +# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) from __future__ import (absolute_import, division, print_function) from functools import reduce diff --git a/simplified_bsd.txt b/simplified_bsd.txt new file mode 100644 index 0000000..6810e04 --- /dev/null +++ b/simplified_bsd.txt @@ -0,0 +1,8 @@ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + From 97be51ef4560d9e9917cb097989eaf4646a54f29 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 17 Jun 2022 08:27:00 +0200 Subject: [PATCH 34/63] Note added regarding the default config file, ~/.my.cnf (#400) (#402) * Note added for https://github.com/ansible-collections/community.mysql/issues/394 * Update config file notes as discussed * Update plugins/doc_fragments/mysql.py Co-authored-by: Andrew Klychkov Co-authored-by: Andrew Klychkov (cherry picked from commit 0df46e0e673935423e55f5f31682ab96f55fc6ae) Co-authored-by: Chris Croome --- plugins/doc_fragments/mysql.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index 4b531d4..66809c4 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -44,6 +44,9 @@ options: config_file: description: - Specify a config file from which user and password are to be read. + - The default config file, C(~/.my.cnf), if it exists, will be read, even if I(config_file) is not specified. + - The default config file, C(~/.my.cnf), if it exists, must contain a C([client]) section as a MySQL connector requirement. + - To prevent the default config file from being read, set I(config_file) to be an empty string. type: path default: '~/.my.cnf' ca_cert: @@ -98,4 +101,7 @@ notes: - Alternatively, you can use the mysqlclient library instead of MySQL-python (MySQLdb) which supports both Python 2.X and Python >=3.5. See U(https://pypi.org/project/mysqlclient/) how to install it. + - "If credentials from the config file (for example, C(/root/.my.cnf)) are not needed to connect to a database server, but + the file exists and does not contain a C([client]) section, before any other valid directives, it will be read and this + will cause the connection to fail, to prevent this set it to an empty string, (for example C(config_file: ''))." ''' From 6ebf59e234ee404b3d3fa45653eee0197c8dc94e Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 24 Jun 2022 15:07:27 +0200 Subject: [PATCH 35/63] README: update MariaDB versions we test against (#404) (#406) (cherry picked from commit 6f87620d9bf61ea4f6168c0839d2c28f78d09bc9) Co-authored-by: Andrew Klychkov --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3be68b4..4b3763c 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,8 @@ Every voice is important and every idea is valuable. If you have something on yo - mysql 5.7.31 - mysql 8.0.22 -- mariadb 10.3.34 -- mariadb 10.5.9 +- mariadb 10.3.34 (only collection version >= 3) +- mariadb 10.8.3 (only collection version >= 3) ### Database connectors From 99548e10cbbf35e3b567546e785d7dfe5d039e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Tue, 2 Aug 2022 10:08:19 +0200 Subject: [PATCH 36/63] Release 1.4.8 commit (#410) --- CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 13 +++++++++++++ changelogs/fragments/simplified-bsd-license.yml | 2 -- galaxy.yml | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) delete mode 100644 changelogs/fragments/simplified-bsd-license.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 96cfaee..112b294 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.4.8 +====== + +Release Summary +--------------- + +This is the patch release of the ``community.mysql`` collection. +This changelog contains all changes to the modules in this collection that +have been added after the release of ``community.mysql`` 1.4.7. + +Bugfixes +-------- + +- Include ``simplified_bsd.txt`` license file for various module utils. + v1.4.7 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index cb46074..b24e587 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -382,3 +382,16 @@ releases: - 322-mysql_query_fix_false_change_report.yml - 334-mysql_user_fix_logic_on_oncreate.yml release_date: '2022-06-02' + 1.4.8: + changes: + bugfixes: + - Include ``simplified_bsd.txt`` license file for various module utils. + release_summary: 'This is the patch release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules in this collection that + + have been added after the release of ``community.mysql`` 1.4.7.' + fragments: + - 1.4.8.yml + - simplified-bsd-license.yml + release_date: '2022-07-28' diff --git a/changelogs/fragments/simplified-bsd-license.yml b/changelogs/fragments/simplified-bsd-license.yml deleted file mode 100644 index 574a695..0000000 --- a/changelogs/fragments/simplified-bsd-license.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: - - Include ``simplified_bsd.txt`` license file for various module utils. diff --git a/galaxy.yml b/galaxy.yml index f94c962..46e971c 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.7 +version: 1.4.8 readme: README.md authors: - Ansible community From 41e7ce5aaabf33807dd6d770c3374218f7b01b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Wed, 3 Aug 2022 10:26:26 +0200 Subject: [PATCH 37/63] Update galaxy.yml to the next expected version (#412) --- galaxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galaxy.yml b/galaxy.yml index 46e971c..ee76d66 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.8 +version: 1.4.9 readme: README.md authors: - Ansible community From 836a1ce0483752d4adb0f82996dbfad5c877ad41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Fri, 12 Aug 2022 16:51:40 +0200 Subject: [PATCH 38/63] [PR #416/97318559 backport][stable-1] Fix ci python requirements (#418) * :Fix ci python requirements (#416) * Add matrix for python and ansible-core versions for sanity tests * Add python 3.9 to integrations tests * Add python 3.9 to unit tests * Reformat sort by python version first (cherry picked from commit 97318559e5aa976dce668a62daaab258014d75a9) * Fix string to int comparison error 1292 * Fix assert expected changed value * Cut assertion that is incorrect With both connectors, and only in stable-1 apparently, the test is always failed. * Fix bool comparison * Revert separated tests for both connectors * Refactor test using connector.name variable * Refactor filtering of tasks using connector's vars sets during setup * Fix "command not found" and "database doesn't exists" * Fix assertion by not running on failing connectors * Fix missing package when using sha256_password with MySQL 8 --- .github/workflows/ansible-test-plugins.yml | 44 ++++++++++++++++--- .../targets/setup_mysql/vars/main.yml | 1 + .../tasks/config_overrides_defaults.yml | 29 ++++++++---- .../targets/test_mysql_db/tasks/issue-28.yml | 6 +-- .../targets/test_mysql_db/tasks/main.yml | 4 +- .../test_mysql_info/tasks/issue-28.yml | 6 +-- .../test_mysql_query/tasks/issue-28.yml | 6 +-- .../test_mysql_replication/tasks/issue-28.yml | 6 +-- .../tasks/mysql_replication_initial.yml | 17 ++++--- .../test_mysql_user/tasks/issue-121.yml | 2 - .../test_mysql_user/tasks/issue-28.yml | 6 +-- .../tasks/test_user_plugin_auth.yml | 11 +++-- .../tasks/assert_fail_msg.yml | 2 +- .../test_mysql_variables/tasks/assert_var.yml | 4 +- .../tasks/assert_var_output.yml | 2 +- .../test_mysql_variables/tasks/issue-28.yml | 6 +-- .../tasks/mysql_variables.yml | 8 ++-- 17 files changed, 99 insertions(+), 61 deletions(-) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index cf2b864..926a1e9 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -29,6 +29,18 @@ jobs: - stable-2.12 - stable-2.13 - devel + python: + - 3.8 + - 3.9 + exclude: + - python: 3.8 + ansible: stable-2.13 + - python: 3.8 + ansible: devel + - python: 3.9 + ansible: stable-2.11 + - python: 3.9 + ansible: stable-2.12 steps: - name: Check out code @@ -39,7 +51,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: ${{ matrix.python }} - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check @@ -64,6 +76,8 @@ jobs: - devel python: - 3.6 + - 3.8 + - 3.9 connector: - pymysql==0.7.10 - pymysql==0.9.3 @@ -71,14 +85,22 @@ jobs: exclude: - mysql: 8.0.22 connector: pymysql==0.7.10 - - python: 3.8 - ansible: stable-2.11 - python: 3.6 ansible: stable-2.12 - python: 3.6 ansible: stable-2.13 - python: 3.6 ansible: devel + - python: 3.8 + ansible: stable-2.11 + - python: 3.8 + ansible: stable-2.13 + - python: 3.8 + ansible: devel + - python: 3.9 + ansible: stable-2.11 + - python: 3.9 + ansible: stable-2.12 steps: - name: Check out code @@ -89,7 +111,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: ${{ matrix.python }} - name: Install ansible-base (${{ matrix.ansible }}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check @@ -125,6 +147,18 @@ jobs: - stable-2.12 - stable-2.13 - devel + python: + - 3.8 + - 3.9 + exclude: + - python: 3.8 + ansible: stable-2.13 + - python: 3.8 + ansible: devel + - python: 3.9 + ansible: stable-2.11 + - python: 3.9 + ansible: stable-2.12 steps: - name: Check out code @@ -135,7 +169,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: ${{ matrix.python }} - name: Install ansible-base (${{matrix.ansible}}) run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml index 4448ac0..49a2f0d 100644 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ b/tests/integration/targets/setup_mysql/vars/main.yml @@ -23,6 +23,7 @@ install_prereqs: install_python_prereqs: - python3-dev + - python3-cryptography - default-libmysqlclient-dev - build-essential diff --git a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml index 42d8fd7..00d5ab0 100644 --- a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml +++ b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml @@ -11,27 +11,40 @@ - name: Add fake port to config file shell: 'echo "port = {{ fake_port }}" >> {{ config_file }}' -- name: Get pymysql version - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - - name: Add blank line shell: 'echo "" >> {{ config_file }}' - when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=') - + when: + - > + connector_name is not search('pymysql') + or ( + connector_name is search('pymysql') + and connector_ver is version('0.9.3', '>=') + ) - name: Create include_dir file: path: '{{ include_dir }}' state: directory mode: '0777' - when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=') + when: + - > + connector_name is not search('pymysql') + or ( + connector_name is search('pymysql') + and connector_ver is version('0.9.3', '>=') + ) - name: Add include_dir lineinfile: path: '{{ config_file }}' line: '!includedir {{ include_dir }}' insertafter: EOF - when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=') + when: + - > + connector_name is not search('pymysql') + or ( + connector_name is search('pymysql') + and connector_ver is version('0.9.3', '>=') + ) - name: Create database using fake port to connect to, must fail mysql_db: diff --git a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml index 871e92d..d985a0e 100644 --- a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -49,12 +47,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_db: diff --git a/tests/integration/targets/test_mysql_db/tasks/main.yml b/tests/integration/targets/test_mysql_db/tasks/main.yml index 139d5bb..de554c4 100644 --- a/tests/integration/targets/test_mysql_db/tasks/main.yml +++ b/tests/integration/targets/test_mysql_db/tasks/main.yml @@ -28,8 +28,8 @@ - name: remove database if it exists command: > - "{{ mysql_command }} -sse 'drop database {{ db_name }}'" - ignore_errors: True + {{ mysql_command }} -sse 'drop database if exists {{ db_name }}' + ignore_errors: true - name: make sure the test database is not there command: "{{ mysql_command }} {{ db_name }}" diff --git a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml index 955683d..158d5c4 100644 --- a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -47,12 +45,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_info: diff --git a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml index e2b51a6..51d082e 100644 --- a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -47,12 +45,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_query: diff --git a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml index c666820..8c24fc5 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -48,12 +46,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_replication: diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml index 4e90707..fac66e4 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml @@ -199,9 +199,6 @@ - replica_status.Exec_Source_Log_Pos != mysql_primary_status.Position when: mysql8022_and_higher == true - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - - name: Start replica that is already running mysql_replication: <<: *mysql_params @@ -210,10 +207,13 @@ fail_on_error: true register: result + # Task is changed with mysqlclient 2.0.1 and pymysql 0.9.3 - assert: that: - - result is not changed - when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=') + - result is not changed + when: + - connector_name is search('pymysql') + - connector_ver is version('0.9.3', '<=') # Test stopreplica mode: - name: Stop replica using deprecated stopslave choice @@ -237,7 +237,10 @@ fail_on_error: true register: result + # Task is changed with mysqlclient 2.0.1 and pymysql 0.9.3 - assert: that: - - result is not changed - when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=') + - result is not changed + when: + - connector_name is search('pymysql') + - connector_ver is version('0.9.3', '<=') diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-121.yml b/tests/integration/targets/test_mysql_user/tasks/issue-121.yml index d8a9d9e..29241d5 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-121.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-121.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml index a5b3d2a..bb40ec9 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -50,12 +48,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_user: diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml index 3ce9f1b..7f77758 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml @@ -334,12 +334,15 @@ # plugins that are loaded by default are sha2*, but these aren't compatible with pymysql < 0.9, so skip these tests # for those versions. # - - name: Get pymysql version - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: Test plugin auth switching which doesn't work on pymysql < 0.9 - when: pymysql_version.stdout == "" or (pymysql_version.stdout != "" and pymysql_version.stdout is version('0.9', '>=')) + when: + - > + connector_name is not search('pymysql') + or ( + connector_name is search('pymysql') + and connector_ver is version('0.9', '>=') + ) block: - name: Create user with plugin auth (empty auth string) diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml index 4a840b9..e7e0885 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml @@ -22,4 +22,4 @@ - name: assert message failure (expect failed=true) assert: that: - - "output.failed == true" + - "output.failed | bool == true" diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml index 5419f34..704f069 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml @@ -22,7 +22,7 @@ - name: assert output message changed value assert: that: - - "output.changed == {{ changed }}" + - "output.changed | bool == changed | bool" - name: run mysql command to show variable command: "{{ mysql_command }} \"-e show variables like '{{ var_name }}'\"" @@ -31,6 +31,6 @@ - name: assert output mysql variable name and value assert: that: - - "result.changed == true" + - "result.changed | bool == true" - "'{{ var_name }}' in result.stdout" - "'{{ var_value }}' in result.stdout" diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml index f84a468..f9ae318 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml @@ -22,7 +22,7 @@ - name: assert output message changed value assert: that: - - "output.changed == {{ changed }}" + - "output.changed | bool == changed | bool" - set_fact: key_name: "{{ var_name }}" diff --git a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml index 056771e..cbebd78 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml @@ -9,8 +9,6 @@ block: # ============================================================ - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: get server certificate copy: @@ -48,12 +46,12 @@ - assert: that: - result is failed - when: pymysql_version.stdout != "" + when: connector.name.0 is search('pymysql') - assert: that: - result is succeeded - when: pymysql_version.stdout == "" + when: connector.name.0 is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_variables: diff --git a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml index 8a25849..fa694de 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml @@ -151,22 +151,20 @@ # ============================================================ # Verify mysql_variable fails when setting an incorrect value (out of range) # - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - name: set mysql variable value to a number out of range mysql_variables: <<: *mysql_params variable: max_connect_errors - value: -1 + value: '-1' register: oor_result ignore_errors: true - include: assert_var.yml changed=true output={{ oor_result }} var_name=max_connect_errors var_value=1 - when: pymysql_version.stdout == "" + when: connector.name.0 is not search('pymysql') - include: assert_fail_msg.yml output={{ oor_result }} msg='Truncated incorrect' - when: pymysql_version.stdout != "" + when: connector.name.0 is search('pymysql') # ============================================================ # Verify mysql_variable fails when setting an incorrect value (incorrect type) From 4cfdbe64a3973f23b5adbef805aca0ae387287c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Sat, 13 Aug 2022 22:06:12 +0200 Subject: [PATCH 39/63] MAINTAINERS file: add a new maintainer (#419) (#422) (cherry picked from commit 057f81711110d40fb46c2a66e9a9987f8dc70068) Co-authored-by: Andrew Klychkov --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c520538..597aa6c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,3 +1,5 @@ bmalynovytch Jorge-Rodriguez -Andersson007 (andersson007_ in #ansible-community IRC) +rsicart +laurent-indermuehle +Andersson007 (andersson007_ in #ansible-community IRC/Matrix) From 108c4ae72963f2f93eb3de29a41fbc163c89d6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Mon, 22 Aug 2022 12:36:44 +0200 Subject: [PATCH 40/63] Port stable 1 ci changes (#423) (#425) * Add changes from stable-1 integrations tests (PR 418) * Refactor to use connectors' info declared in setup_mysql * Fix 2nd replication stop marked changed by mysqlclient (cherry picked from commit 61586ae4cc169119cb3fa9824fdfe9f5aeb46308) --- .../tasks/config_overrides_defaults.yml | 1 + .../tasks/mysql_query_initial.yml | 4 ++-- .../tasks/mysql_replication_initial.yml | 18 ++++++++++-------- .../tasks/test_user_plugin_auth.yml | 1 - .../tasks/assert_var_output.yml | 2 +- .../test_mysql_variables/tasks/issue-28.yml | 4 ++-- .../tasks/mysql_variables.yml | 4 ++-- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml index 00d5ab0..c2fda2a 100644 --- a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml +++ b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml @@ -20,6 +20,7 @@ connector_name is search('pymysql') and connector_ver is version('0.9.3', '>=') ) + - name: Create include_dir file: path: '{{ include_dir }}' diff --git a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml index 2d971ab..5bf379f 100644 --- a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml +++ b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml @@ -343,7 +343,7 @@ that: # PyMySQL driver throws a warning, so the following is correct - result is not changed - when: connector.name.0 is search('pymysql') + when: connector_name is search('pymysql') # Issue https://github.com/ansible-collections/community.mysql/issues/268 - assert: @@ -352,7 +352,7 @@ # if the state was changed or not. # We assume that it was for DDL queryes by default in the code - result is changed - when: connector.name.0 is search('mysqlclient') + when: connector_name is search('mysqlclient') - name: Drop db {{ test_db }} mysql_query: diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml index fac66e4..55ee6cb 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml @@ -176,8 +176,8 @@ shell: "echo \"INSERT INTO {{ test_table }} (id) VALUES (1), (2), (3); FLUSH LOGS;\" | {{ mysql_command }} -P{{ mysql_primary_port }} {{ test_db }}" - name: Small pause to be sure the bin log, which was flushed previously, reached the replica - pause: - seconds: 2 + ansible.builtin.wait_for: + timeout: 2 # Test master log pos has been changed: - name: Get replica status @@ -207,13 +207,12 @@ fail_on_error: true register: result - # Task is changed with mysqlclient 2.0.1 and pymysql 0.9.3 + # mysqlclient 2.0.1 always return "changed" - assert: that: - result is not changed when: - - connector_name is search('pymysql') - - connector_ver is version('0.9.3', '<=') + - connector_name == 'pymysql' # Test stopreplica mode: - name: Stop replica using deprecated stopslave choice @@ -228,7 +227,12 @@ - result is changed - result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"] + - name: Pause for 2 seconds to let the replication stop + ansible.builtin.wait_for: + timeout: 2 + # Test stopreplica mode: + # mysqlclient 2.0.1 always return "changed" - name: Stop replica that is no longer running mysql_replication: <<: *mysql_params @@ -237,10 +241,8 @@ fail_on_error: true register: result - # Task is changed with mysqlclient 2.0.1 and pymysql 0.9.3 - assert: that: - result is not changed when: - - connector_name is search('pymysql') - - connector_ver is version('0.9.3', '<=') + - connector_name == 'pymysql' diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml index 7f77758..465c687 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml @@ -334,7 +334,6 @@ # plugins that are loaded by default are sha2*, but these aren't compatible with pymysql < 0.9, so skip these tests # for those versions. # - - name: Test plugin auth switching which doesn't work on pymysql < 0.9 when: - > diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml index f9ae318..01362ef 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml @@ -35,6 +35,6 @@ - name: assert output variable info match mysql variable info assert: that: - - "result.changed == true" + - "result.changed | bool == true" - "key_name in result.stdout" - "key_value in result.stdout" diff --git a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml index cbebd78..3e27eda 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml @@ -46,12 +46,12 @@ - assert: that: - result is failed - when: connector.name.0 is search('pymysql') + when: connector_name is search('pymysql') - assert: that: - result is succeeded - when: connector.name.0 is not search('pymysql') + when: connector_name is not search('pymysql') - name: attempt connection with newly created user ignoring hostname mysql_variables: diff --git a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml index fa694de..3ef3c3a 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml @@ -161,10 +161,10 @@ ignore_errors: true - include: assert_var.yml changed=true output={{ oor_result }} var_name=max_connect_errors var_value=1 - when: connector.name.0 is not search('pymysql') + when: connector_name is not search('pymysql') - include: assert_fail_msg.yml output={{ oor_result }} msg='Truncated incorrect' - when: connector.name.0 is search('pymysql') + when: connector_name is search('pymysql') # ============================================================ # Verify mysql_variable fails when setting an incorrect value (incorrect type) From c199000eeeb5aff402f6a80d2cc07df79f241f8b Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Fri, 26 Aug 2022 13:41:06 +0200 Subject: [PATCH 41/63] Docs: add info how to cope with a protocol-related connection error using login_unix_socket argument (#420) (#431) (cherry picked from commit f1d63e3fc8a9669b5c2d1a6c913c30414b1cb5cd) --- plugins/doc_fragments/mysql.py | 3 +++ plugins/modules/mysql_db.py | 3 +++ plugins/modules/mysql_info.py | 3 +++ plugins/modules/mysql_query.py | 3 +++ plugins/modules/mysql_replication.py | 3 +++ plugins/modules/mysql_user.py | 3 +++ plugins/modules/mysql_variables.py | 3 +++ 7 files changed, 21 insertions(+) diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index 66809c4..7d4ec96 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -35,6 +35,7 @@ options: login_unix_socket: description: - The path to a Unix domain socket for local connections. + - Use this parameter to avoid the C(Please explicitly state intended protocol) error. type: str connect_timeout: description: @@ -78,6 +79,8 @@ requirements: - PyMySQL (Python 2.7 and Python 3.x) or - MySQLdb (Python 2.x) notes: + - "To avoid the C(Please explicitly state intended protocol) error, use the I(login_unix_socket) argument, + for example, C(login_unix_socket: /run/mysqld/mysqld.sock)." - Requires the PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) package installed on the remote host. The Python package may be installed with apt-get install python-pymysql (Ubuntu; see M(ansible.builtin.apt)) or yum install python2-PyMySQL (RHEL/CentOS/Fedora; see M(ansible.builtin.yum)). You can also use dnf install python2-PyMySQL diff --git a/plugins/modules/mysql_db.py b/plugins/modules/mysql_db.py index 52da021..1f45e34 100644 --- a/plugins/modules/mysql_db.py +++ b/plugins/modules/mysql_db.py @@ -183,10 +183,13 @@ extends_documentation_fragment: ''' EXAMPLES = r''' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Create a new database with name 'bobdata' community.mysql.mysql_db: name: bobdata state: present + login_unix_socket: /run/mysqld/mysqld.sock - name: Create new databases with names 'foo' and 'bar' community.mysql.mysql_db: diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 6f57403..1daa9b9 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -76,9 +76,12 @@ EXAMPLES = r''' # Display all info from databases group except settings: # ansible databases -m mysql_info -a 'filter=!settings' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Collect all possible information using passwordless root access community.mysql.mysql_info: login_user: root + login_unix_socket: /run/mysqld/mysqld.sock - name: Get MySQL version with non-default credentials community.mysql.mysql_info: diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index a91335b..04f6201 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -57,10 +57,13 @@ extends_documentation_fragment: ''' EXAMPLES = r''' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Simple select query to acme db community.mysql.mysql_query: login_db: acme query: SELECT * FROM orders + login_unix_socket: /run/mysqld/mysqld.sock - name: Select query to db acme with positional arguments community.mysql.mysql_query: diff --git a/plugins/modules/mysql_replication.py b/plugins/modules/mysql_replication.py index 981074f..20f9d6c 100644 --- a/plugins/modules/mysql_replication.py +++ b/plugins/modules/mysql_replication.py @@ -191,9 +191,12 @@ seealso: ''' EXAMPLES = r''' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Stop mysql replica thread community.mysql.mysql_replication: mode: stopreplica + login_unix_socket: /run/mysqld/mysqld.sock - name: Get master binlog file name and binlog position community.mysql.mysql_replication: diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 1151d92..b8e7479 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -152,11 +152,14 @@ extends_documentation_fragment: ''' EXAMPLES = r''' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Removes anonymous user account for localhost community.mysql.mysql_user: name: '' host: localhost state: absent + login_unix_socket: /run/mysqld/mysqld.sock - name: Removes all anonymous user accounts community.mysql.mysql_user: diff --git a/plugins/modules/mysql_variables.py b/plugins/modules/mysql_variables.py index 06beee3..2544e8d 100644 --- a/plugins/modules/mysql_variables.py +++ b/plugins/modules/mysql_variables.py @@ -58,9 +58,12 @@ extends_documentation_fragment: ''' EXAMPLES = r''' +# If you encounter the "Please explicitly state intended protocol" error, +# use the login_unix_socket argument - name: Check for sync_binlog setting community.mysql.mysql_variables: variable: sync_binlog + login_unix_socket: /run/mysqld/mysqld.sock - name: Set read_only variable to 1 persistently community.mysql.mysql_variables: From 275d85067a6f03e3c99121efd1b8439673084efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Mon, 29 Aug 2022 10:19:31 +0200 Subject: [PATCH 42/63] [PR #427/0a68bb27 backport][stable-1] CI is changed (#428) * Is changed (#427) * Refactor tests to use "is" and "is not" changed * Refactor tests to use is succeeded or is failed * Reformat indentation * Add filter "bool" to prevent issues (cherry picked from commit 0a68bb270f64957fc30d263080ca10c9f4d20f6c) * Fix error message verification I don't know why this works on main, but in stable-1, the error message is "invalid privileges string: Invalid privileges specified: frozenset({'INVALID'})" * Add filter for test that won't work with mariadb * Refactor test in their own file instead of main * Add db_names dict * Fix registered variable name * Add missing fact * Add test databases cleanup * Cut tests for unsupported db name (%) * Add missing default vars to tests db_formats * Backport small diff from main --- .../targets/test_mysql_db/defaults/main.yml | 13 +- .../tasks/encoding_dump_import.yml | 3 +- .../targets/test_mysql_db/tasks/main.yml | 325 ++---------------- .../tasks/multi_db_create_delete.yml | 42 ++- .../test_mysql_db/tasks/state_dump_import.yml | 16 +- .../tasks/state_present_absent.yml | 300 ++++++++++++++++ .../targets/test_mysql_info/tasks/main.yml | 58 ++-- .../tasks/mysql_query_initial.yml | 128 +++---- .../tasks/assert_user_password.yml | 24 ++ .../test_mysql_user/tasks/create_user.yml | 2 +- .../test_mysql_user/tasks/issue-64560.yaml | 8 +- .../targets/test_mysql_user/tasks/main.yml | 10 +- .../test_mysql_user/tasks/remove_user.yml | 6 +- .../tasks/test_priv_append.yml | 4 +- .../test_mysql_user/tasks/test_privs.yml | 27 +- .../tasks/test_user_password.yml | 30 +- .../tasks/test_user_plugin_auth.yml | 90 +++-- .../tasks/tls_requirements.yml | 27 +- .../tasks/assert_fail_msg.yml | 2 +- .../test_mysql_variables/tasks/assert_var.yml | 2 +- .../tasks/assert_var_output.yml | 2 +- .../tasks/mysql_variables.yml | 5 +- 22 files changed, 631 insertions(+), 493 deletions(-) create mode 100644 tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml diff --git a/tests/integration/targets/test_mysql_db/defaults/main.yml b/tests/integration/targets/test_mysql_db/defaults/main.yml index b6ae780..1c1577b 100644 --- a/tests/integration/targets/test_mysql_db/defaults/main.yml +++ b/tests/integration/targets/test_mysql_db/defaults/main.yml @@ -4,7 +4,18 @@ mysql_user: root mysql_password: msandbox mysql_primary_port: 3307 -db_name: 'data' +# Database names +db_names: + - "data" + # - "db%" + # Don't test % in stable-1. Support was added in v2 + +# Database formats +db_formats: + - { format_type: "sql", file: "dbdata.sql", format_msg_type: "ASCII", file2: "dump2.sql", file3: "dump3.sql", file4: "dump4.sql" } + - { format_type: "gz", file: "dbdata.gz", format_msg_type: "gzip", file2: "dump2.gz", file3: "dump3.gz", file4: "dump4.gz" } + - { format_type: "bz2", file: "dbdata.bz2", format_msg_type: "bzip2", file2: "dump2.bz2", file3: "dump3.bz2", file4: "dump4.bz2" } + db_name2: 'data2' db_user1: 'datauser1' db_user2: 'datauser2' diff --git a/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml b/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml index 173386c..9ef3af5 100644 --- a/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml +++ b/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml @@ -45,7 +45,7 @@ encoding: latin1 target: "{{ latin1_file1 }}" state: dump - register: dump_result + register: result - assert: that: @@ -78,6 +78,7 @@ encoding: latin1 name: '{{ db_latin1_name }}' target: "{{ latin1_file1 }}" + register: result - assert: that: diff --git a/tests/integration/targets/test_mysql_db/tasks/main.yml b/tests/integration/targets/test_mysql_db/tasks/main.yml index de554c4..958e341 100644 --- a/tests/integration/targets/test_mysql_db/tasks/main.yml +++ b/tests/integration/targets/test_mysql_db/tasks/main.yml @@ -21,306 +21,45 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . -# ============================================================ - name: alias mysql command to include default options set_fact: mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" -- name: remove database if it exists - command: > - {{ mysql_command }} -sse 'drop database if exists {{ db_name }}' - ignore_errors: true +- name: Check state present/absent + include_tasks: state_present_absent.yml + vars: + db_name: "{{ item }}" + loop: "{{ db_names }}" -- name: make sure the test database is not there - command: "{{ mysql_command }} {{ db_name }}" - register: mysql_db_check - failed_when: "'1049' not in mysql_db_check.stderr" +- name: Check state dump/import + include_tasks: state_dump_import.yml + vars: + db_name: "{{ item.0 }}" + file: "{{ item.1.file }}" + file2: "{{ item.1.file2 }}" + file3: "{{ item.1.file3 }}" + file4: "{{ item.1.file4 }}" + format_msg_type: "{{ item.1.format_msg_type }}" + format_type: "{{ item.1.format_type }}" + with_nested: + - "{{ db_names }}" + - "{{ db_formats }}" -- name: test state=present for a database name (expect changed=true) - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_name }}' - state: present - register: result +- name: Check state present/absent with multiple databases + include_tasks: multi_db_create_delete.yml -- name: assert output message that database exist - assert: - that: - - result is changed - - result.db == '{{ db_name }}' - - result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"] +- name: Check state dump/import with encoding + include_tasks: encoding_dump_import.yml + vars: + file: "latin1.sql" + format_msg_type: "ASCII" -- name: run command to test state=present for a database name (expect db_name in stdout) - command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\"" - register: result - -- name: assert database exist - assert: - that: - - "'{{ db_name }}' in result.stdout" - -# ============================================================ -- name: test state=absent for a database name (expect changed=true) - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_name }}' - state: absent - register: result - -- name: assert output message that database does not exist - assert: - that: - - result is changed - - result.db == '{{ db_name }}' - - result.executed_commands == ["DROP DATABASE `{{ db_name }}`"] - -- name: run command to test state=absent for a database name (expect db_name not in stdout) - command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\"" - register: result - -- name: assert database does not exist - assert: - that: - - "'{{ db_name }}' not in result.stdout" - -# ============================================================ -- name: test mysql_db encoding param not valid - issue 8075 - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: datanotvalid - state: present - encoding: notvalid - register: result - ignore_errors: true - -- name: assert test mysql_db encoding param not valid - issue 8075 (failed=true) - assert: - that: - - "result.failed == true" - - "'Traceback' not in result.msg" - - "'Unknown character set' in result.msg" - -# ============================================================ -- name: test mysql_db using a valid encoding utf8 (expect changed=true) - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: 'en{{ db_name }}' - state: present - encoding: utf8 - register: result - -- name: assert output message created a database - assert: - that: - - result is changed - - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"] - -- name: test database was created - command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE en{{ db_name }}\"" - register: result - -- name: assert created database is of encoding utf8 - assert: - that: - - "'utf8' in result.stdout" - -- name: remove database - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: 'en{{ db_name }}' - state: absent - -# ============================================================ -- name: test mysql_db using valid encoding binary (expect changed=true) - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: 'en{{ db_name }}' - state: present - encoding: binary - register: result - -- name: assert output message that database was created - assert: - that: - - result is changed - - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"] - -- name: run command to test database was created - command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE en{{ db_name }}\"" - register: result - -- name: assert created database is of encoding binary - assert: - that: - - "'binary' in result.stdout" - -- name: remove database - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: 'en{{ db_name }}' - state: absent - -# ============================================================ -- name: create user1 to access database dbuser1 - mysql_user: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: user1 - password: 'Hfd6fds^dfA8Ga' - priv: '*.*:ALL' - state: present - -- name: create database dbuser1 using user1 - mysql_db: - login_user: user1 - login_password: 'Hfd6fds^dfA8Ga' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_user1 }}' - state: present - register: result - -- name: assert output message that database was created - assert: - that: - - "result.changed == true" - -- name: run command to test database was created using user1 - command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 }}'\"" - register: result - -- name: assert database exist - assert: - that: - - "'{{ db_user1 }}' in result.stdout" - -# ============================================================ -- name: create user2 to access database with privilege select only - mysql_user: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: user2 - password: 'kjsfd&F7safjad' - priv: '*.*:SELECT' - state: present - -- name: create database dbuser2 using user2 with no privilege to create (expect failed=true) - mysql_db: - login_user: user2 - login_password: 'kjsfd&F7safjad' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_user2 }}' - state: present - register: result - ignore_errors: true - -- name: assert output message that database was not created using dbuser2 - assert: - that: - - "result.failed == true" - - "'Access denied' in result.msg" - -- name: run command to test that database was not created - command: "{{ mysql_command }} -e \"show databases like '{{ db_user2 }}'\"" - register: result - -- name: assert database does not exist - assert: - that: - - "'{{ db_user2 }}' not in result.stdout" - -# ============================================================ -- name: delete database using user2 with no privilege to delete (expect failed=true) - mysql_db: - login_user: user2 - login_password: 'kjsfd&F7safjad' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_user1 }}' - state: absent - register: result - ignore_errors: true - -- name: assert output message that database was not deleted using dbuser2 - assert: - that: - - "result.failed == true" - - "'Access denied' in result.msg" - -- name: run command to test database was not deleted - command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 }}'\"" - register: result - -- name: assert database still exist - assert: - that: - - "'{{ db_user1 }}' in result.stdout" - -# ============================================================ -- name: delete database using user1 with all privilege to delete a database (expect changed=true) - mysql_db: - login_user: user1 - login_password: 'Hfd6fds^dfA8Ga' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_user1 }}' - state: absent - register: result - ignore_errors: true - -- name: assert output message that database was deleted using user1 - assert: - that: - - result is changed - - result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"] - -- name: run command to test database was deleted using user1 - command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\"" - register: result - -- name: assert database does not exist - assert: - that: - - "'{{ db_user1 }}' not in result.stdout" - -# ============================================================ -- include: state_dump_import.yml format_type=sql file=dbdata.sql format_msg_type=ASCII file2=dump2.sql file3=dump3.sql file4=dump4.sql - -- include: state_dump_import.yml format_type=gz file=dbdata.gz format_msg_type=gzip file2=dump2.gz file3=dump3.gz file4=dump4.gz - -- include: state_dump_import.yml format_type=bz2 file=dbdata.bz2 format_msg_type=bzip2 file2=dump2.bz2 file3=dump3.bz2 file4=dump4.bz2 - -- include: multi_db_create_delete.yml - -- include: encoding_dump_import.yml file=latin1.sql format_msg_type=ASCII - -- include: config_overrides_defaults.yml +- name: Check MySQL config file + include_tasks: config_overrides_defaults.yml when: ansible_python.version_info[0] >= 3 -- include: issue-28.yml +- name: Check issue 28 + include_tasks: issue-28.yml + vars: + db_name: "{{ item }}" + loop: "{{ db_names }}" diff --git a/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml b/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml index 6bada1c..c2eb13c 100644 --- a/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml +++ b/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml @@ -14,6 +14,18 @@ # # ========================================================================== # Initial check - To confirm that database does not exist before executing check mode tasks +- name: Drop databases before test + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: + - '{{ db1_name }}' + - '{{ db2_name }}' + - '{{ db3_name }}' + state: absent + - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" register: mysql_result @@ -44,7 +56,7 @@ - name: assert successful completion of create database using check_mode since databases does not exist prior assert: that: - - check_mode_result.changed == true + - check_mode_result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -75,7 +87,7 @@ - name: assert successful completion of create database assert: that: - - result.changed == true + - result is changed - result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}'] - name: run command to list databases like specified database name @@ -108,7 +120,7 @@ - name: assert that recreation of existing databases does not make change (since recreated using check mode) assert: that: - - check_mode_result.changed == false + - check_mode_result is not changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -139,7 +151,7 @@ - name: assert that recreation of existing databases does not make change assert: that: - - result.changed == false + - result is not changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -168,7 +180,7 @@ - name: assert successful completion of deleting database assert: that: - - result.changed == true + - result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -200,7 +212,7 @@ - name: assert successful completion of recreation of partially existing database using check mode assert: that: - - check_mode_result.changed == true + - check_mode_result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -231,7 +243,7 @@ - name: assert successful completion of create database assert: that: - - result.changed == true + - result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -272,7 +284,7 @@ - name: assert successful completion of dump operation using check mode assert: that: - - check_mode_dump_result.changed == true + - check_mode_dump_result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -389,7 +401,7 @@ - name: assert successful completion of dump operation assert: that: - - dump_result.changed == true + - dump_result is changed - dump_result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}'] - name: run command to list databases like specified database name @@ -439,7 +451,7 @@ - name: assert successful completion of dump operation assert: that: - - dump_result.changed == true + - dump_result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -479,7 +491,7 @@ - name: assert successful completion of delete databases which already exists using check mode assert: that: - - check_mode_result.changed == true + - check_mode_result is changed - name: run command to test state=absent for a database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -508,7 +520,7 @@ - name: assert successful completion of deleting database assert: that: - - result.changed == true + - result is changed - result.db_list == ['{{ db2_name }}', '{{ db3_name }}'] - name: run command to list databases like specified database name @@ -539,7 +551,7 @@ - name: assert that deletion of non existing databases does not make change (using check mode) assert: that: - - check_mode_result.changed == false + - check_mode_result is not changed - name: run command to test state=absent for a database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -568,7 +580,7 @@ - name: assert that deletion of non existing databases does not make change assert: that: - - result.changed == false + - result is not changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" @@ -600,7 +612,7 @@ - name: assert successful completion of deleting database assert: that: - - result.changed == true + - result is changed - name: run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" diff --git a/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml b/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml index 1de7439..6d904b9 100644 --- a/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml +++ b/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml @@ -159,7 +159,7 @@ - name: assert successful completion of dump operation (with multiple databases in list form) via check mode assert: that: - - "dump_result.changed == true" + - dump_result is changed - name: database dump file2 should not exist stat: @@ -187,7 +187,7 @@ - name: assert successful completion of dump operation (with multiple databases in list form) assert: that: - - "dump_result2.changed == true" + - dump_result2 is changed - name: state dump - dump file2 should exist file: @@ -249,7 +249,7 @@ - name: assert output message restored a database from dump file1 assert: that: - - "import_result.changed == true" + - import_result is changed - name: remove database mysql_db: @@ -284,7 +284,7 @@ - name: assert output message restored a database from dump file2 (check mode) assert: that: - - "check_import_result.changed == true" + - check_import_result is changed - name: run command to list databases command: "{{ mysql_command }} \"-e show databases like 'data%'\"" @@ -309,7 +309,7 @@ - name: assert output message restored a database from dump file2 assert: that: - - import_result2.changed == true + - import_result2 is changed - import_result2.db_list == ['{{ db_name2 }}'] - name: run command to list databases @@ -335,7 +335,7 @@ - name: assert output message backup the database assert: that: - - "result.changed == true" + - result is changed - "result.db =='{{ db_name }}'" # - name: assert database was backed up successfully @@ -364,7 +364,7 @@ - name: assert output message restore the database assert: that: - - "result.changed == true" + - result is changed - name: select data from table employee command: "{{ mysql_command }} {{ db_name }} \"-e select * from employee\"" @@ -398,7 +398,7 @@ - assert: that: - - result.failed == true + - result is failed - name: try to import with force parameter mysql_db: diff --git a/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml b/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml new file mode 100644 index 0000000..5b6e871 --- /dev/null +++ b/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml @@ -0,0 +1,300 @@ +# test code for mysql_db module with database name containing special chars + +# 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 . + +# ============================================================ +- name: remove database if it exists + command: > + "{{ mysql_command }} -sse 'DROP DATABASE IF EXISTS {{ db_name }}'" + ignore_errors: true + +- name: make sure the test database is not there + command: "{{ mysql_command }} {{ db_name }}" + register: mysql_db_check + failed_when: "'1049' not in mysql_db_check.stderr" + +- name: test state=present for a database name (expect changed=true) + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_name }}' + state: present + register: result + +- name: assert output message that database exist + assert: + that: + - result is changed + - result.db == '{{ db_name }}' + - result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"] + +- name: run command to test state=present for a database name (expect db_name in stdout) + command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database exist + assert: + that: + - "'{{ db_name }}' in result.stdout" + +# ============================================================ +- name: test state=absent for a database name (expect changed=true) + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_name }}' + state: absent + register: result + +- name: assert output message that database does not exist + assert: + that: + - result is changed + - result.db == '{{ db_name }}' + - result.executed_commands == ["DROP DATABASE `{{ db_name }}`"] + +- name: run command to test state=absent for a database name (expect db_name not in stdout) + command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database does not exist + assert: + that: + - "'{{ db_name }}' not in result.stdout" + +# ============================================================ +- name: test mysql_db encoding param not valid - issue 8075 + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: datanotvalid + state: present + encoding: notvalid + register: result + ignore_errors: true + +- name: assert test mysql_db encoding param not valid - issue 8075 (failed=true) + assert: + that: + - result is failed + - "'Traceback' not in result.msg" + - "'Unknown character set' in result.msg" + +# ============================================================ +- name: test mysql_db using a valid encoding utf8 (expect changed=true) + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: 'en{{ db_name }}' + state: present + encoding: utf8 + register: result + +- name: assert output message created a database + assert: + that: + - result is changed + - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"] + +- name: test database was created + command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\"" + register: result + +- name: assert created database is of encoding utf8 + assert: + that: + - "'utf8' in result.stdout" + +- name: remove database + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: 'en{{ db_name }}' + state: absent + +# ============================================================ +- name: test mysql_db using valid encoding binary (expect changed=true) + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: 'en{{ db_name }}' + state: present + encoding: binary + register: result + +- name: assert output message that database was created + assert: + that: + - result is changed + - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"] + +- name: run command to test database was created + command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\"" + register: result + +- name: assert created database is of encoding binary + assert: + that: + - "'binary' in result.stdout" + +- name: remove database + mysql_db: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: 'en{{ db_name }}' + state: absent + +# ============================================================ +- name: create user1 to access database dbuser1 + mysql_user: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: user1 + password: 'Hfd6fds^dfA8Ga' + priv: '*.*:ALL' + state: present + +- name: create database dbuser1 using user1 + mysql_db: + login_user: user1 + login_password: 'Hfd6fds^dfA8Ga' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_user1 }}' + state: present + register: result + +- name: assert output message that database was created + assert: + that: + - result is changed + +- name: run command to test database was created using user1 + command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database exist + assert: + that: + - "'{{ db_user1 }}' in result.stdout" + +# ============================================================ +- name: create user2 to access database with privilege select only + mysql_user: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: user2 + password: 'kjsfd&F7safjad' + priv: '*.*:SELECT' + state: present + +- name: create database dbuser2 using user2 with no privilege to create (expect failed=true) + mysql_db: + login_user: user2 + login_password: 'kjsfd&F7safjad' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_user2 }}' + state: present + register: result + ignore_errors: true + +- name: assert output message that database was not created using dbuser2 + assert: + that: + - result is failed + - "'Access denied' in result.msg" + +- name: run command to test that database was not created + command: "{{ mysql_command }} -e \"show databases like '{{ db_user2 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database does not exist + assert: + that: + - "'{{ db_user2 }}' not in result.stdout" + +# ============================================================ +- name: delete database using user2 with no privilege to delete (expect failed=true) + mysql_db: + login_user: user2 + login_password: 'kjsfd&F7safjad' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_user1 }}' + state: absent + register: result + ignore_errors: true + +- name: assert output message that database was not deleted using dbuser2 + assert: + that: + - result is failed + - "'Access denied' in result.msg" + +- name: run command to test database was not deleted + command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database still exist + assert: + that: + - "'{{ db_user1 }}' in result.stdout" + +# ============================================================ +- name: delete database using user1 with all privilege to delete a database (expect changed=true) + mysql_db: + login_user: user1 + login_password: 'Hfd6fds^dfA8Ga' + login_host: 127.0.0.1 + login_port: '{{ mysql_primary_port }}' + name: '{{ db_user1 }}' + state: absent + register: result + ignore_errors: true + +- name: assert output message that database was deleted using user1 + assert: + that: + - result is changed + - result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"] + +- name: run command to test database was deleted using user1 + command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" + register: result + +- name: assert database does not exist + assert: + that: + - "'{{ db_user1 }}' not in result.stdout" diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index 0ed2af9..ec2bd9b 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -47,8 +47,8 @@ - assert: that: - - result.changed == false - - "mysql_version in result.version.full" + - result is not changed + - "mysql_version in result.version.full or mariadb_version in result.version.full" - result.settings != {} - result.global_status != {} - result.databases != {} @@ -66,7 +66,7 @@ - assert: that: - - result.changed == false + - result is not changed - result.version != {} # Remove cred files @@ -86,8 +86,8 @@ - assert: that: - - result.changed == false - - result.version != {} + - result is not changed + - result.version != {} # Test excluding - name: Collect all info except settings and users @@ -98,13 +98,13 @@ - assert: that: - - result.changed == false - - result.version != {} - - result.global_status != {} - - result.databases != {} - - result.engines != {} - - result.settings is not defined - - result.users is not defined + - result is not changed + - result.version != {} + - result.global_status != {} + - result.databases != {} + - result.engines != {} + - result.settings is not defined + - result.users is not defined # Test including - name: Collect info only about version and databases @@ -117,13 +117,13 @@ - assert: that: - - result.changed == false - - result.version != {} - - result.databases != {} - - result.engines is not defined - - result.settings is not defined - - result.global_status is not defined - - result.users is not defined + - result is not changed + - result.version != {} + - result.databases != {} + - result.engines is not defined + - result.settings is not defined + - result.global_status is not defined + - result.users is not defined # Test exclude_fields: db_size # 'unsupported' element is passed to check that an unsupported value @@ -140,9 +140,9 @@ - assert: that: - - result.changed == false - - result.databases != {} - - result.databases.mysql == {} + - result is not changed + - result.databases != {} + - result.databases.mysql == {} ######################################################## # Issue #65727, empty databases must be in returned dict @@ -163,9 +163,9 @@ # Check acme is in returned dict - assert: that: - - result.changed == false - - result.databases.acme.size == 0 - - result.databases.mysql != {} + - result is not changed + - result.databases.acme.size == 0 + - result.databases.mysql != {} - name: Collect info about databases excluding their sizes mysql_info: @@ -180,9 +180,9 @@ # Check acme is in returned dict - assert: that: - - result.changed == false - - result.databases.acme == {} - - result.databases.mysql == {} + - result is not changed + - result.databases.acme == {} + - result.databases.mysql == {} - name: Remove acme database mysql_db: @@ -212,4 +212,4 @@ - name: Check assert: that: - result.databases.allviews.size == 0 + - result.databases.allviews.size == 0 diff --git a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml index 5bf379f..cbb7b53 100644 --- a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml +++ b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml @@ -18,8 +18,8 @@ - assert: that: - - result is changed - - result.executed_queries == ['CREATE DATABASE {{ test_db }}'] + - result is changed + - result.executed_queries == ['CREATE DATABASE {{ test_db }}'] - name: Create {{ test_table1 }} mysql_query: @@ -30,8 +30,8 @@ - assert: that: - - result is changed - - result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)'] + - result is changed + - result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)'] - name: Insert test data mysql_query: @@ -45,9 +45,9 @@ - assert: that: - - result is changed - - result.rowcount == [2, 1] - - result.executed_queries == ['INSERT INTO {{ test_table1 }} VALUES (1), (2)', 'INSERT INTO {{ test_table1 }} VALUES (3)'] + - result is changed + - result.rowcount == [2, 1] + - result.executed_queries == ['INSERT INTO {{ test_table1 }} VALUES (1), (2)', 'INSERT INTO {{ test_table1 }} VALUES (3)'] - name: Check data in {{ test_table1 }} mysql_query: @@ -58,12 +58,12 @@ - assert: that: - - result is not changed - - result.executed_queries == ['SELECT * FROM {{ test_table1 }}'] - - result.rowcount == [3] - - result.query_result[0][0].id == 1 - - result.query_result[0][1].id == 2 - - result.query_result[0][2].id == 3 + - result is not changed + - result.executed_queries == ['SELECT * FROM {{ test_table1 }}'] + - result.rowcount == [3] + - result.query_result[0][0].id == 1 + - result.query_result[0][1].id == 2 + - result.query_result[0][2].id == 3 - name: Check data in {{ test_table1 }} using positional args mysql_query: @@ -76,10 +76,10 @@ - assert: that: - - result is not changed - - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] - - result.rowcount == [1] - - result.query_result[0][0].id == 1 + - result is not changed + - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] + - result.rowcount == [1] + - result.query_result[0][0].id == 1 - name: Check data in {{ test_table1 }} using named args mysql_query: @@ -92,10 +92,10 @@ - assert: that: - - result is not changed - - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] - - result.rowcount == [1] - - result.query_result[0][0].id == 1 + - result is not changed + - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] + - result.rowcount == [1] + - result.query_result[0][0].id == 1 - name: Update data in {{ test_table1 }} mysql_query: @@ -109,9 +109,9 @@ - assert: that: - - result is changed - - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] - - result.rowcount == [1] + - result is changed + - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] + - result.rowcount == [1] - name: Check the prev update - row with value 1 does not exist anymore mysql_query: @@ -124,9 +124,9 @@ - assert: that: - - result is not changed - - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1'] - - result.rowcount == [0] + - result is not changed + - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1'] + - result.rowcount == [0] - name: Check the prev update - row with value - exist mysql_query: @@ -139,9 +139,9 @@ - assert: that: - - result is not changed - - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0'] - - result.rowcount == [1] + - result is not changed + - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0'] + - result.rowcount == [1] - name: Update data in {{ test_table1 }} again mysql_query: @@ -155,9 +155,9 @@ - assert: that: - - result is not changed - - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] - - result.rowcount == [0] + - result is not changed + - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] + - result.rowcount == [0] - name: Delete data from {{ test_table1 }} mysql_query: @@ -170,9 +170,9 @@ - assert: that: - - result is changed - - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0'] - - result.rowcount == [1, 0] + - result is changed + - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0'] + - result.rowcount == [1, 0] - name: Delete data from {{ test_table1 }} again mysql_query: @@ -183,9 +183,9 @@ - assert: that: - - result is not changed - - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0'] - - result.rowcount == [0] + - result is not changed + - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0'] + - result.rowcount == [0] - name: Truncate {{ test_table1 }} mysql_query: @@ -198,9 +198,9 @@ - assert: that: - - result is changed - - result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}'] - - result.rowcount == [0, 0] + - result is changed + - result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}'] + - result.rowcount == [0, 0] - name: Rename {{ test_table1 }} mysql_query: @@ -211,9 +211,9 @@ - assert: that: - - result is changed - - result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}'] - - result.rowcount == [0] + - result is changed + - result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}'] + - result.rowcount == [0] - name: Check the prev rename mysql_query: @@ -225,7 +225,7 @@ - assert: that: - - result.failed == true + - result is failed - name: Check the prev rename mysql_query: @@ -236,7 +236,7 @@ - assert: that: - - result.rowcount == [0] + - result.rowcount == [0] - name: Create {{ test_table3 }} mysql_query: @@ -259,7 +259,7 @@ - assert: that: - - result.rowcount == [2] + - result.rowcount == [2] - name: Pass wrong query type mysql_query: @@ -271,8 +271,8 @@ - assert: that: - - result is failed - - result.msg is search('the query option value must be a string or list') + - result is failed + - result.msg is search('the query option value must be a string or list') - name: Pass wrong query element mysql_query: @@ -286,8 +286,8 @@ - assert: that: - - result is failed - - result.msg is search('the elements in query list must be strings') + - result is failed + - result.msg is search('the elements in query list must be strings') - name: Create {{ test_table4 }} mysql_query: @@ -305,8 +305,8 @@ - assert: that: - - result is changed - - result.rowcount == [1] + - result is changed + - result.rowcount == [1] - name: Replace test data mysql_query: @@ -318,8 +318,8 @@ - assert: that: - - result is changed - - result.rowcount == [2] + - result is changed + - result.rowcount == [2] # Issue https://github.com/ansible-collections/community.mysql/issues/268 - name: Create table @@ -341,17 +341,17 @@ # Issue https://github.com/ansible-collections/community.mysql/issues/268 - assert: that: - # PyMySQL driver throws a warning, so the following is correct - - result is not changed + # PyMySQL driver throws a warning, so the following is correct + - result is not changed when: connector_name is search('pymysql') # Issue https://github.com/ansible-collections/community.mysql/issues/268 - assert: that: - # mysqlclient driver throws nothing, so it's impossible to figure out - # if the state was changed or not. - # We assume that it was for DDL queryes by default in the code - - result is changed + # mysqlclient driver throws nothing, so it's impossible to figure out + # if the state was changed or not. + # We assume that it was for DDL queryes by default in the code + - result is changed when: connector_name is search('mysqlclient') - name: Drop db {{ test_db }} @@ -362,5 +362,5 @@ - assert: that: - - result is changed - - result.executed_queries == ['DROP DATABASE {{ test_db }}'] + - result is changed + - result.executed_queries == ['DROP DATABASE {{ test_db }}'] diff --git a/tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml b/tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml new file mode 100644 index 0000000..ba045eb --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml @@ -0,0 +1,24 @@ +- name: "applying user {{ username }}@{{ host }} with update_password={{ update_password }}" + mysql_user: + login_user: '{{ mysql_parameters.login_user }}' + login_password: '{{ mysql_parameters.login_password }}' + login_host: '{{ mysql_parameters.login_host }}' + login_port: '{{ mysql_parameters.login_port }}' + state: present + name: "{{ username }}" + host: "{{ host }}" + password: "{{ password }}" + update_password: "{{ update_password }}" + register: result +- name: assert a change occurred + assert: + that: + - "result.changed | bool == {{ expect_change }} | bool" + - "result.password_changed == {{ expect_password_change }}" +- name: query the user + command: "{{ mysql_command }} -BNe \"SELECT plugin, authentication_string FROM mysql.user where user='{{ username }}' and host='{{ host }}'\"" + register: existing_user +- name: assert the password is as set to expect_hash + assert: + that: + - "'mysql_native_password\t{{ expect_password_hash }}' in existing_user.stdout_lines" diff --git a/tests/integration/targets/test_mysql_user/tasks/create_user.yml b/tests/integration/targets/test_mysql_user/tasks/create_user.yml index 790d9bb..9c3459a 100644 --- a/tests/integration/targets/test_mysql_user/tasks/create_user.yml +++ b/tests/integration/targets/test_mysql_user/tasks/create_user.yml @@ -37,4 +37,4 @@ - name: assert output message mysql user was created assert: that: - - "result.changed == true" + - result is changed diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml b/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml index 46078b2..1c0af68 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml @@ -17,7 +17,9 @@ register: result - name: assert root password is changed - assert: { that: "result.changed == true" } + assert: + that: + - result is changed - name: Set root password again mysql_user: @@ -31,7 +33,9 @@ register: result - name: Assert root password is not changed - assert: { that: "result.changed == false" } + assert: + that: + - result is not changed - name: Set root password again mysql_user: diff --git a/tests/integration/targets/test_mysql_user/tasks/main.yml b/tests/integration/targets/test_mysql_user/tasks/main.yml index 9b6caf3..5ddf300 100644 --- a/tests/integration/targets/test_mysql_user/tasks/main.yml +++ b/tests/integration/targets/test_mysql_user/tasks/main.yml @@ -65,7 +65,9 @@ register: result - name: assert output message mysql user was not created - assert: { that: "result.changed == false" } + assert: + that: + - result is not changed # ============================================================ # remove mysql user and verify user is removed from mysql database @@ -81,7 +83,7 @@ - name: assert output message mysql user was removed assert: that: - - "result.changed == true" + - result is changed - include: assert_no_user.yml user_name={{user_name_1}} @@ -99,7 +101,7 @@ - name: assert output message mysql user that does not exist assert: that: - - "result.changed == false" + - result is not changed - include: assert_no_user.yml user_name={{user_name_1}} @@ -242,7 +244,9 @@ # ============================================================ # Test plugin authentication scenarios. # + # FIXME: mariadb sql syntax for create/update user is not compatible - include: test_user_plugin_auth.yml + when: install_type == 'mysql' # ============================================================ # Assert create user with SELECT privileges, attempt to create database and update privileges to create database diff --git a/tests/integration/targets/test_mysql_user/tasks/remove_user.yml b/tests/integration/targets/test_mysql_user/tasks/remove_user.yml index 45a0ad4..7a2c9e9 100644 --- a/tests/integration/targets/test_mysql_user/tasks/remove_user.yml +++ b/tests/integration/targets/test_mysql_user/tasks/remove_user.yml @@ -37,7 +37,7 @@ - name: assert output message mysql user was removed assert: that: - - "result.changed == true" + - result is changed # ============================================================ - name: create blank mysql user to be removed later @@ -58,7 +58,7 @@ - name: assert changed is true for removing all blank users assert: that: - - "result.changed == true" + - result is changed - name: remove blank mysql user with hosts=all (expect ok) mysql_user: @@ -71,4 +71,4 @@ - name: assert changed is true for removing all blank users assert: that: - - "result.changed == false" + - result is not changed diff --git a/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml b/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml index 7dc15ca..72e933b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml @@ -50,7 +50,7 @@ - name: Assert that there wasn't a change in permissions assert: that: - - "result.changed == false" + - result is not changed - name: Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" @@ -76,7 +76,7 @@ - name: Assert that there was a change because permissions were added to data1.* assert: that: - - "result.changed == true" + - result is changed - name: Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" diff --git a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml index 4ed75d1..17e42b3 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml @@ -51,7 +51,7 @@ - name: assert output message for current privileges assert: that: - - "result.changed == true" + - result is changed - name: run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{user_name_2}}'@'localhost'\"" @@ -101,7 +101,7 @@ - name: Assert that priv changed assert: that: - - "result.changed == true" + - result is changed - name: Add privs to a specific table (expect ok) mysql_user: @@ -115,7 +115,7 @@ - name: Assert that priv did not change assert: that: - - "result.changed == false" + - result is not changed # ============================================================ - name: update user with all privileges @@ -162,7 +162,7 @@ - name: Assert that priv changed assert: that: - - "result.changed == true" + - result is changed - name: Test idempotency (expect ok) mysql_user: @@ -176,7 +176,24 @@ - name: Assert that priv did not change assert: that: - - "result.changed == false" + - result is not changed + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.2', '==')) + + # ============================================================ + - name: update user with invalid privileges + mysql_user: + <<: *mysql_params + name: '{{ user_name_2 }}' + password: '{{ user_password_2 }}' + priv: '*.*:INVALID' + state: present + register: result + ignore_errors: yes + + - name: Assert that priv did not change + assert: + that: + - result is failed - name: remove username mysql_user: diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml index f3b0e06..57d8d29 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml @@ -32,7 +32,7 @@ - name: Assert that a change occurred because the user was added assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -49,7 +49,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Run mysql_user again without any changes mysql_user: @@ -63,7 +63,7 @@ - name: Assert that there weren't any changes because username/password didn't change assert: that: - - "result.changed == false" + - result is not changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -78,7 +78,7 @@ - name: Assert that a change occurred because the password was updated assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -95,7 +95,7 @@ - name: Assert that the mysql_info module failed because we used the old password assert: that: - - "result.failed == true" + - result is failed - name: Get the MySQL version data using the new password (should work) mysql_info: @@ -110,7 +110,7 @@ - name: Assert that the mysql_info module succeeded because we used the new password assert: that: - - "result.failed == false" + - result is succeeded # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} @@ -131,7 +131,7 @@ - name: Assert that a change occurred because the user was added assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -148,7 +148,7 @@ - name: Assert that there weren't any changes because username/password didn't change assert: that: - - "result.changed == false" + - result is not changed # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} @@ -170,7 +170,7 @@ - name: Assert that a change occurred because the user was added assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -187,7 +187,7 @@ - name: Assert that the mysql_info module succeeded because we used the new password assert: that: - - "result.failed == false" + - result is succeeded - name: Pass in the same password as before, but in the encrypted form (no change expected) mysql_user: @@ -200,7 +200,7 @@ - name: Assert that there weren't any changes because username/password didn't change assert: that: - - "result.changed == false" + - result is not changed # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} @@ -220,7 +220,7 @@ - name: Assert that a change occurred because the user was added assert: that: - - "result.changed == true" + - result is changed - name: Get the MySQL version using an empty password for the newly created user mysql_info: @@ -235,7 +235,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Get the MySQL version using an non-empty password (should fail) mysql_info: @@ -250,7 +250,7 @@ - name: Assert that mysql_info failed assert: that: - - "result.failed == true" + - result is failed - name: Update the user without changing the password mysql_user: @@ -263,7 +263,7 @@ - name: Assert that the user wasn't changed because the password is still empty assert: that: - - "result.changed == false" + - result is not changed # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password='' diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml index 465c687..264d8bd 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml @@ -31,14 +31,19 @@ register: result - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change + assert: + that: + - result is changed + + - name: Check that the expected plugin type is set assert: that: - - "result.changed == true" - "'{{ test_plugin_type }}' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -54,7 +59,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Update the user with a different hash mysql_user: @@ -67,7 +72,7 @@ - name: Check that the module makes the change because the hash changed assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -83,7 +88,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_new_auth_string }} @@ -102,14 +107,19 @@ register: result - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change + assert: + that: + - result is changed + + - name: Check that the expected plugin type is set assert: that: - - "result.changed == true" - "'{{ test_plugin_type }}' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -125,7 +135,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Update the user with the same hash (no change expected) mysql_user: @@ -135,10 +145,12 @@ plugin_hash_string: '{{ test_plugin_hash }}' register: result + # FIXME: on mariadb 10.2 there's always a change - name: Check that the module doesn't make a change when the same hash is passed in assert: that: - - "result.changed == false" + - result is not changed + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -154,7 +166,7 @@ - name: Check that the module did not change the password assert: that: - - "result.changed == true" + - result is changed - name: Getting the MySQL info should still work mysql_info: @@ -168,7 +180,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} @@ -190,11 +202,16 @@ command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change + assert: + that: + - result is changed + + - name: Check that the expected plugin type is set assert: that: - - "result.changed == true" - "'{{ test_plugin_type }}' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -210,7 +227,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Update the user with the same auth string mysql_user: @@ -225,7 +242,7 @@ - name: The module should detect a change even though the password is the same assert: that: - - "result.changed == true" + - result is changed - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -240,7 +257,7 @@ - name: Check that the module did not change the password assert: that: - - "result.changed == false" + - result is not changed - name: Get the MySQL version using the newly created creds mysql_info: @@ -254,7 +271,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} @@ -275,11 +292,16 @@ command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change + assert: + that: + - result is changed + + - name: Check that the expected plugin type is set assert: that: - - "result.changed == true" - "'{{ test_plugin_type }}' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -296,7 +318,7 @@ - name: Assert that mysql_info was successful assert: that: - - "result.failed == false" + - result is succeeded - name: Get the MySQL version using an non-empty password (should fail) mysql_info: @@ -311,7 +333,7 @@ - name: Assert that mysql_info failed assert: that: - - "result.failed == true" + - result is failed - name: Update the user without changing the auth mechanism mysql_user: @@ -324,7 +346,7 @@ - name: Assert that the user wasn't changed because the auth string is still empty assert: that: - - "result.changed == false" + - result is not changed # Cleanup - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} @@ -356,11 +378,16 @@ command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change + assert: + that: + - result is changed + + - name: Check that the expected plugin type is set assert: that: - - "result.changed == true" - "'{{ test_plugin_type }}' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} @@ -376,11 +403,16 @@ command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" register: show_create_user - - name: Check that the module made a change and that the expected plugin type is set + - name: Check that the module made a change assert: that: - - "result.changed == true" - - "'sha256_password' in show_create_user.stdout" + - result is changed + + - name: Check that the expected plugin type is set + assert: + that: + - "'sha256_password' in show_create_user.stdout" + when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} diff --git a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml b/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml index 8de9401..73cab1b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml +++ b/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml @@ -55,7 +55,7 @@ issuer: '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' - block: - - name: retrieve TLS requiremets for users in old database version + - name: retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ item }}'@'localhost'\"" register: old_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] @@ -67,7 +67,7 @@ when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - block: - - name: retrieve TLS requiremets for users in new database version + - name: retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ item }}'@'localhost'\"" register: new_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] @@ -119,12 +119,12 @@ that: - result is changed - - name: retrieve TLS requiremets for users in old database version + - name: retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" register: old_result when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - - name: retrieve TLS requiremets for users in new database version + - name: retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: new_result when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 @@ -143,12 +143,12 @@ tls_requires: X509: - - name: retrieve TLS requiremets for users in old database version + - name: retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" register: old_result when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 - - name: retrieve TLS requiremets for users in new database version + - name: retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: new_result when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 @@ -159,28 +159,21 @@ vars: - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - - name: remove TLS requiremets from user (expect changed=true) + - name: remove TLS requirements from user (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' tls_requires: - - name: retrieve TLS requiremets for users in old database version + - name: retrieve TLS requirements for users command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" - register: old_result - when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 + register: result - - name: retrieve TLS requiremets for users in new database version - command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" - register: new_result - when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 - name: assert user1 TLS requirements assert: - that: "'NONE' in reqs" - vars: - - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip() | default('NONE') }}" + that: "'REQUIRE ' not in result.stdout or 'REQUIRE NONE' in result.stdout" - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml index e7e0885..a09bcdb 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_fail_msg.yml @@ -22,4 +22,4 @@ - name: assert message failure (expect failed=true) assert: that: - - "output.failed | bool == true" + - output is failed diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml index 704f069..96d196d 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml @@ -31,6 +31,6 @@ - name: assert output mysql variable name and value assert: that: - - "result.changed | bool == true" + - result is changed - "'{{ var_name }}' in result.stdout" - "'{{ var_value }}' in result.stdout" diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml index 01362ef..6f26386 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var_output.yml @@ -35,6 +35,6 @@ - name: assert output variable info match mysql variable info assert: that: - - "result.changed | bool == true" + - result is changed - "key_name in result.stdout" - "key_value in result.stdout" diff --git a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml index 3ef3c3a..ed34966 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml @@ -151,7 +151,6 @@ # ============================================================ # Verify mysql_variable fails when setting an incorrect value (out of range) # - - name: set mysql variable value to a number out of range mysql_variables: <<: *mysql_params @@ -360,7 +359,9 @@ - include: assert_var.yml changed=true output={{ result }} var_name={{ set_name }} var_value='{{ def_val }}' - when: mysql_version is not version('8.0', '<') + when: + - mysql_version is version('8.0', '>=') + - install_type == 'mysql' # Bugfix of https://github.com/ansible/ansible/issues/54239 # - name: set variable containing dot From d363315ecb267ebd72fa0a923306926fa6f2008e Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 09:48:56 +0200 Subject: [PATCH 43/63] Combine REVIEW_CHECKLIST.md and CONTRIBUTING.md and fix links (#432) (#440) (cherry picked from commit ea73d408c3e31982346add6965bd330173d8c64d) Co-authored-by: Maxwell G <9920591+gotmax23@users.noreply.github.com> --- CONTRIBUTING.md | 4 +++- REVIEW_CHECKLIST.md | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) delete mode 100644 REVIEW_CHECKLIST.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edcfe55..70cd555 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,5 @@ # Contributing -Refer to the [Ansible Contributing guidelines](https://github.com/ansible/community-docs/blob/main/contributing.rst) to learn how to contribute to this collection. +Refer to the [Ansible Contributing guidelines](https://docs.ansible.com/ansible/devel/community/index.html) to learn how to contribute to this collection. + +Refer to the [review checklist](https://docs.ansible.com/ansible/devel/community/collection_contributors/collection_reviewing.html) when triaging issues or reviewing PRs. diff --git a/REVIEW_CHECKLIST.md b/REVIEW_CHECKLIST.md deleted file mode 100644 index 9dccf7e..0000000 --- a/REVIEW_CHECKLIST.md +++ /dev/null @@ -1,3 +0,0 @@ -# Review Checklist - -Refer to the [Collection review checklist](https://github.com/ansible/community-docs/blob/main/review_checklist.rst). From 786470058c88fc79856eb888b977d398ea37d78a Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 16 Sep 2022 16:15:25 +0200 Subject: [PATCH 44/63] Fix: devel requires python 3.9 in roles CI (#444) (#447) * Fix: devel requires python 3.9 Package 'ansible-core' requires a different Python: 3.8.13 not in '>=3.9' * Exclude older version of Ansible when testing Python 3.9 (cherry picked from commit 2cd29207f3e68e253e99774a05b25e10dddc9fc9) Co-authored-by: R.Sicart --- .github/workflows/ansible-test-roles.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index bda6986..34bee52 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -30,15 +30,24 @@ jobs: python: - 3.6 - 3.8 + - 3.9 exclude: - - python: 3.8 - ansible: stable-2.11 - python: 3.6 ansible: stable-2.12 - python: 3.6 ansible: stable-2.13 - python: 3.6 ansible: devel + - python: 3.8 + ansible: stable-2.11 + - python: 3.8 + ansible: stable-2.13 + - python: 3.8 + ansible: devel + - python: 3.9 + ansible: stable-2.11 + - python: 3.9 + ansible: stable-2.12 steps: From 40da237de79d7f38dadc757eba09a1a2821f45b3 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 07:06:15 +0200 Subject: [PATCH 45/63] CI: add stable-2.14 to test matrix (#449) (#451) (cherry picked from commit b8e2c02e89524344f37e88d1c42e61bdd71796a4) Co-authored-by: Andrew Klychkov --- .github/workflows/ansible-test-plugins.yml | 11 +++++++++++ tests/sanity/ignore-2.15.txt | 8 ++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/sanity/ignore-2.15.txt diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 926a1e9..c6c5d38 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -28,6 +28,7 @@ jobs: - stable-2.11 - stable-2.12 - stable-2.13 + - stable-2.14 - devel python: - 3.8 @@ -35,6 +36,8 @@ jobs: exclude: - python: 3.8 ansible: stable-2.13 + - python: 3.8 + ansible: stable-2.14 - python: 3.8 ansible: devel - python: 3.9 @@ -73,6 +76,7 @@ jobs: - stable-2.11 - stable-2.12 - stable-2.13 + - stable-2.14 - devel python: - 3.6 @@ -89,12 +93,16 @@ jobs: ansible: stable-2.12 - python: 3.6 ansible: stable-2.13 + - python: 3.6 + ansible: stable-2.14 - python: 3.6 ansible: devel - python: 3.8 ansible: stable-2.11 - python: 3.8 ansible: stable-2.13 + - python: 3.8 + ansible: stable-2.14 - python: 3.8 ansible: devel - python: 3.9 @@ -146,6 +154,7 @@ jobs: - stable-2.11 - stable-2.12 - stable-2.13 + - stable-2.14 - devel python: - 3.8 @@ -153,6 +162,8 @@ jobs: exclude: - python: 3.8 ansible: stable-2.13 + - python: 3.8 + ansible: stable-2.14 - python: 3.8 ansible: devel - python: 3.9 diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt new file mode 100644 index 0000000..c0323af --- /dev/null +++ b/tests/sanity/ignore-2.15.txt @@ -0,0 +1,8 @@ +plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen +plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch +plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements +plugins/modules/mysql_user.py validate-modules:undocumented-parameter +plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch From 2020870155ec51698f8331467e13606206dc5516 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 13:29:25 +0200 Subject: [PATCH 46/63] * add `socket` option suggestion in documentation (#437) (#454) * * add `socket` option suggestion in documentation * white space fix * * move first two at the end (cherry picked from commit b9a6ec4f7d5c8e7293cb3f84e333d1f5fba20be8) Co-authored-by: Gabriel PREDA --- .gitignore | 3 +++ plugins/doc_fragments/mysql.py | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6bbe85a..1922df0 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,6 @@ dmypy.json # MacOS .DS_Store + +# IntelliJ IDEA or PyCharm +.idea/ diff --git a/plugins/doc_fragments/mysql.py b/plugins/doc_fragments/mysql.py index 7d4ec96..939126c 100644 --- a/plugins/doc_fragments/mysql.py +++ b/plugins/doc_fragments/mysql.py @@ -79,8 +79,6 @@ requirements: - PyMySQL (Python 2.7 and Python 3.x) or - MySQLdb (Python 2.x) notes: - - "To avoid the C(Please explicitly state intended protocol) error, use the I(login_unix_socket) argument, - for example, C(login_unix_socket: /run/mysqld/mysqld.sock)." - Requires the PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) package installed on the remote host. The Python package may be installed with apt-get install python-pymysql (Ubuntu; see M(ansible.builtin.apt)) or yum install python2-PyMySQL (RHEL/CentOS/Fedora; see M(ansible.builtin.yum)). You can also use dnf install python2-PyMySQL @@ -107,4 +105,9 @@ notes: - "If credentials from the config file (for example, C(/root/.my.cnf)) are not needed to connect to a database server, but the file exists and does not contain a C([client]) section, before any other valid directives, it will be read and this will cause the connection to fail, to prevent this set it to an empty string, (for example C(config_file: ''))." + - "To avoid the C(Please explicitly state intended protocol) error, use the I(login_unix_socket) argument, + for example, C(login_unix_socket: /run/mysqld/mysqld.sock)." + - Alternatively, to avoid using I(login_unix_socket) argument on each invocation you can specify the socket path + using the `socket` option in your MySQL config file (usually C(~/.my.cnf)) on the destination host, for + example C(socket=/var/lib/mysql/mysql.sock). ''' From fadbd30572be22fbc64149f204e5a08e12191c8c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 1 Nov 2022 13:27:51 +0100 Subject: [PATCH 47/63] README: Add matrix room + badge (#459) (#460) * README: Add matrix room + badge * improve (cherry picked from commit 09e02320fd15c51a80183cde80b059e2b9e44dfd) Co-authored-by: Andrew Klychkov --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b3763c..e8c2295 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MySQL collection for Ansible -[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) +[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) [![](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20at%20%23mysql:ansible.com&logo=matrix)] This collection is a part of the Ansible package. @@ -36,7 +36,7 @@ They also should be subscribed to Ansible's [The Bullhorn newsletter](https://do We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). Be sure you are subscribed. -Join us in the `#ansible` (general use questions and support), `#ansible-community` (community and collection development questions), and other [IRC channels](https://docs.ansible.com/ansible/devel/community/communication.html#irc-channels) on [Libera.Chat](https://libera.chat). +Join us on Matrix in the `#mysql:ansible.com` [room](https://matrix.to/#/#mysql:ansible.com), the `#users:ansible.com` [room](https://matrix.to/#/#users:ansible.com) (general use questions and support), `#ansible-community:ansible.com` [room](https://matrix.to/#/#community:ansible.com) (community and collection development questions), and other Matrix rooms or corresponding bridged Libera.Chat channels. See the [Ansible Communication Guide](https://docs.ansible.com/ansible/devel/community/communication.html) for details. We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us. From 85a63511b6596d50fc2d61281901c201744f7c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Thu, 10 Nov 2022 15:00:42 +0100 Subject: [PATCH 48/63] Backport/stable 1/pr 452 (#464) * Sync GHA workflow w/ the collection template (#452) * Sync GHA workflow w/ the collection template * Drop the trailing pre-cmd semicolon * Recover missing `-e` flag of `sed` * Use relative paths for version configs * Unquote `env.connector_version_file` * Use string formatting to fix the substitution problem (cherry picked from commit 81075307442c943ba2661dcbf5cd59459f89083c) (cherry picked from commit 704a0cea6a7a3501dbe1d4875386e1dccbe5afa8) * Backport mysql_version_parts variable assignation (cherry picked from commit 79046a88cbdc4c417243e029ea3a87f10fd67cd6) (cherry picked from commit a59d95501e9a2c2fcd38449d14ee22231cee8e45) * Add changelog fragment (cherry picked from commit 26ecd6880153f018a62734874a216f0daa78f933) * Backport flags and variables to differentiate MariaDB from MySQL setup (cherry picked from commit b4303511d5a6202d0a85b0cb4c379a15e32390bf) * Backport issue-28 check for tls support (cherry picked from commit efde607d2550863a1fdc98f752d75482a15e3677) * Backport tls_requirements simplified and deduplified tests (cherry picked from commit ac5a33964498498c127b37b095875422b97af22f) Co-authored-by: Sviatoslav Sydorenko --- .github/workflows/ansible-test-plugins.yml | 137 ++++++------------ .../fragments/backport-stable-2-pr-452.yml | 4 + .../targets/setup_mysql/defaults/main.yml | 9 +- .../targets/setup_mysql/tasks/config.yml | 4 +- .../targets/setup_mysql/tasks/install.yml | 18 ++- .../targets/setup_mysql/tasks/setvars.yml | 7 +- .../targets/setup_mysql/vars/main.yml | 11 +- .../targets/test_mysql_db/tasks/issue-28.yml | 8 +- .../test_mysql_info/tasks/issue-28.yml | 12 +- .../test_mysql_query/tasks/issue-28.yml | 12 +- .../test_mysql_replication/tasks/issue-28.yml | 12 +- .../test_mysql_replication/tasks/main.yml | 2 + .../tasks/mysql_replication_initial.yml | 8 +- .../test_mysql_user/tasks/issue-28.yml | 8 +- .../tasks/tls_requirements.yml | 3 +- .../test_mysql_variables/tasks/issue-28.yml | 8 +- 16 files changed, 146 insertions(+), 117 deletions(-) create mode 100644 changelogs/fragments/backport-stable-2-pr-452.yml diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index c6c5d38..4303152 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -15,12 +15,12 @@ on: env: - mysql_version_file: "./ansible_collections/community/mysql/tests/integration/targets/setup_mysql/defaults/main.yml" - connector_version_file: "./ansible_collections/community/mysql/tests/integration/targets/setup_mysql/vars/main.yml" + mysql_version_file: "tests/integration/targets/setup_mysql/defaults/main.yml" + connector_version_file: "tests/integration/targets/setup_mysql/vars/main.yml" jobs: sanity: - name: "Sanity (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }})" + name: "Sanity (Ansible: ${{ matrix.ansible }})" runs-on: ubuntu-latest strategy: matrix: @@ -30,48 +30,22 @@ jobs: - stable-2.13 - stable-2.14 - devel - python: - - 3.8 - - 3.9 - exclude: - - python: 3.8 - ansible: stable-2.13 - - python: 3.8 - ansible: stable-2.14 - - python: 3.8 - ansible: devel - - python: 3.9 - ansible: stable-2.11 - - python: 3.9 - ansible: stable-2.12 steps: - - - name: Check out code - uses: actions/checkout@v2 + - name: Perform sanity testing + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ansible_collections/community/mysql - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - - name: Run sanity tests - run: ansible-test sanity --docker -v --color - working-directory: ./ansible_collections/community/mysql + ansible-core-version: ${{ matrix.ansible }} + testing-type: sanity integration: - name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.mysql }}, Connector: ${{ matrix.connector }})" + name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.db_engine_version }}, Connector: ${{ matrix.connector }})" runs-on: ubuntu-latest strategy: fail-fast: false matrix: - mysql: - - 5.7.31 - - 8.0.22 + db_engine_version: + - mysql_5.7.31 + - mysql_8.0.22 ansible: - stable-2.11 - stable-2.12 @@ -87,7 +61,7 @@ jobs: - pymysql==0.9.3 - mysqlclient==2.0.1 exclude: - - mysql: 8.0.22 + - db_engine_version: mysql_8.0.22 connector: pymysql==0.7.10 - python: 3.6 ansible: stable-2.12 @@ -110,37 +84,31 @@ jobs: - python: 3.9 ansible: stable-2.12 steps: - - - name: Check out code - uses: actions/checkout@v2 + - name: >- + Perform integration testing against + Ansible version ${{ matrix.ansible }} + under Python ${{ matrix.python }} + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ansible_collections/community/mysql - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - - name: Set MySQL version (${{ matrix.mysql }}) - run: "sed -i 's/^mysql_version:.*/mysql_version: \"${{ matrix.mysql }}\"/g' ${{ env.mysql_version_file }}" - - - name: Set Connector version (${{ matrix.connector }}) - run: "sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }}" - - - name: Run integration tests - run: ansible-test integration --docker -v --color --retry-on-error --continue-on-error --python ${{ matrix.python }} --diff --coverage - working-directory: ./ansible_collections/community/mysql - - - name: Generate coverage report. - run: ansible-test coverage xml -v --requirements --group-by command --group-by version - working-directory: ./ansible_collections/community/mysql - - - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: false + ansible-core-version: ${{ matrix.ansible }} + pre-test-cmd: >- + DB_ENGINE=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $1}'); + DB_VERSION=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $2}'); + DB_ENGINE_PRETTY=$([[ "${DB_ENGINE}" == 'mysql' ]] && echo 'MySQL' || echo 'MariaDB'); + >&2 echo Matrix factor for the DB is ${{ matrix.db_engine_version }}...; + >&2 echo Setting ${DB_ENGINE_PRETTY} version to ${DB_VERSION}...; + sed -i -e "s/^${DB_ENGINE}_version:.*/${DB_ENGINE}_version: $DB_VERSION/g" -e 's/^mariadb_install: false/mariadb_install: true/g' '${{ env.mysql_version_file }}'; + ${{ + matrix.db_engine_version == 'mariadb_10.8.3' + && format( + '>&2 echo Set MariaDB v10.8.3 URL sub dir...; sed -i -e "s/^mariadb_url_subdir:.*/mariadb_url_subdir: linux-systemd/g" "{0}";', env.connector_version_file + ) + || '' + }} + >&2 echo Setting Connector version to ${{ matrix.connector }}...; + sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }} + target-python-version: ${{ matrix.python }} + testing-type: integration units: runs-on: ubuntu-latest @@ -172,30 +140,11 @@ jobs: ansible: stable-2.12 steps: - - name: Check out code - uses: actions/checkout@v2 + - name: >- + Perform unit testing against + Ansible version ${{ matrix.ansible }} + uses: ansible-community/ansible-test-gh-action@release/v1 with: - path: ./ansible_collections/community/mysql - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python }} - - - name: Install ansible-base (${{matrix.ansible}}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check - - # Run the unit tests - - name: Run unit test - run: ansible-test units -v --color --docker --coverage - working-directory: ./ansible_collections/community/mysql - - # ansible-test support producing code coverage date - - name: Generate coverage report - run: ansible-test coverage xml -v --requirements --group-by command --group-by version - working-directory: ./ansible_collections/community/mysql - - # See the reports at https://codecov.io/gh/GITHUBORG/REPONAME - - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: false + ansible-core-version: ${{ matrix.ansible }} + target-python-version: ${{ matrix.python }} + testing-type: units diff --git a/changelogs/fragments/backport-stable-2-pr-452.yml b/changelogs/fragments/backport-stable-2-pr-452.yml new file mode 100644 index 0000000..ee84ae2 --- /dev/null +++ b/changelogs/fragments/backport-stable-2-pr-452.yml @@ -0,0 +1,4 @@ +--- + +trivial: + - Tests - Backport PR-452 Sync GHA workflow w/ the collection template diff --git a/tests/integration/targets/setup_mysql/defaults/main.yml b/tests/integration/targets/setup_mysql/defaults/main.yml index 2908c17..cceb8f5 100644 --- a/tests/integration/targets/setup_mysql/defaults/main.yml +++ b/tests/integration/targets/setup_mysql/defaults/main.yml @@ -3,11 +3,16 @@ dbdeployer_home_dir: /opt/dbdeployer home_dir: /root -percona_client_version: 5.7 - mariadb_install: false mysql_version: 8.0.22 mariadb_version: 10.5.4 mysql_base_port: 3306 + +percona_client_package: >- + {%- if mariadb_install -%} + mariadb-client + {%- else -%} + percona-server-client-5.7 + {%- endif -%} diff --git a/tests/integration/targets/setup_mysql/tasks/config.yml b/tests/integration/targets/setup_mysql/tasks/config.yml index 57be29a..2b27e27 100644 --- a/tests/integration/targets/setup_mysql/tasks/config.yml +++ b/tests/integration/targets/setup_mysql/tasks/config.yml @@ -6,10 +6,10 @@ - name: "{{ role_name }} | config | run unpack tarball" shell: - cmd: "dbdeployer unpack {{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }}" + cmd: "dbdeployer unpack {{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }} --flavor {{ install_type }}" creates: "{{ dbdeployer_sandbox_binary_dir }}/{{ install_version }}" - name: "{{ role_name }} | config | setup replication topology" shell: - cmd: "dbdeployer deploy multiple {{ install_version }} --base-port {{ mysql_base_port }} --my-cnf-options=\"master_info_repository='TABLE'\" --my-cnf-options=\"relay_log_info_repository='TABLE'\"" + cmd: "dbdeployer deploy multiple {{ install_version }} --flavor {{ install_type }} --base-port {{ mysql_base_port }} --my-cnf-options=\"master_info_repository='TABLE'\" --my-cnf-options=\"relay_log_info_repository='TABLE'\"" creates: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}" diff --git a/tests/integration/targets/setup_mysql/tasks/install.yml b/tests/integration/targets/setup_mysql/tasks/install.yml index 57e4b31..b64af25 100644 --- a/tests/integration/targets/setup_mysql/tasks/install.yml +++ b/tests/integration/targets/setup_mysql/tasks/install.yml @@ -4,12 +4,26 @@ keyserver: keyserver.ubuntu.com id: 4D1BB29D63D98E422B2113B19334A25F8507EFA5 state: present + when: install_type == 'mysql' - name: "{{ role_name }} | install | add percona repositories" apt_repository: - repo: "{{ item }}" + repo: deb http://repo.percona.com/percona/apt {{ ansible_lsb.codename }} main state: present - loop: "{{ percona_mysql_repos }}" + when: install_type == 'mysql' + +- name: "{{ role_name }} | install | add apt signing key for mariadb" + apt_key: + keyserver: keyserver.ubuntu.com + id: F1656F24C74CD1D8 + state: present + when: install_type == 'mariadb' + +- name: "{{ role_name }} | install | add mariadb repositories" + apt_repository: + repo: "deb [arch=amd64,arm64] https://downloads.mariadb.com/MariaDB/mariadb-{{ mysql_major_version }}/repo/ubuntu {{ ansible_lsb.codename }} main" + state: present + when: install_type == 'mariadb' - name: "{{ role_name }} | install | install packages required by percona" apt: diff --git a/tests/integration/targets/setup_mysql/tasks/setvars.yml b/tests/integration/targets/setup_mysql/tasks/setvars.yml index 14a2c54..cfc90c1 100644 --- a/tests/integration/targets/setup_mysql/tasks/setvars.yml +++ b/tests/integration/targets/setup_mysql/tasks/setvars.yml @@ -1,7 +1,12 @@ --- - name: "{{ role_name }} | setvars | split mysql version in parts" set_fact: - mysql_version_parts: "{{ mysql_version.split('.') }}" + mysql_version_parts: >- + {%- if mariadb_install -%} + {{ mariadb_version.split('.') }} + {%- else -%} + {{ mysql_version.split('.') }} + {%- endif -%} - name: "{{ role_name }} | setvars | get mysql major version" set_fact: diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml index 49a2f0d..4aa52a2 100644 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ b/tests/integration/targets/setup_mysql/vars/main.yml @@ -7,12 +7,8 @@ dbdeployer_sandbox_download_dir: "{{ home_dir }}/downloads" dbdeployer_sandbox_binary_dir: "{{ home_dir }}/opt/mysql" dbdeployer_sandbox_home_dir: "{{ home_dir }}/sandboxes" -percona_mysql_repos: - - deb http://repo.percona.com/apt {{ ansible_lsb.codename }} main - - deb-src http://repo.percona.com/apt {{ ansible_lsb.codename }} main - percona_mysql_packages: - - percona-server-client-{{ percona_client_version }} + - "{{ percona_client_package }}" python_packages: [pymysql == 0.9.3] @@ -29,5 +25,6 @@ install_python_prereqs: mysql_tarball: "mysql-{{ mysql_version }}-linux-glibc2.12-x86_64.tar.{{ mysql_compression_extension }}" mysql_src: "https://dev.mysql.com/get/Downloads/MySQL-{{ mysql_major_version }}/{{ mysql_tarball }}" -mariadb_tarball: "mariadb-{{ mariadb_version }}-linux-x86_64.tar.gz" -mariadb_src: "https://downloads.mariadb.com/MariaDB/mariadb-{{ mariadb_version }}/bintar-linux-x86_64/{{ mariadb_tarball }}" +mariadb_url_subdir: "linux" +mariadb_tarball: "mariadb-{{ mariadb_version }}-{{ mariadb_url_subdir }}-x86_64.tar.gz" +mariadb_src: "https://downloads.mariadb.com/MariaDB/mariadb-{{ mariadb_version }}/bintar-{{ mariadb_url_subdir }}-x86_64/{{ mariadb_tarball }}" diff --git a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml index d985a0e..54ff5a7 100644 --- a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml @@ -1,11 +1,17 @@ --- +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ diff --git a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml index 158d5c4..068fbb3 100644 --- a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml @@ -1,11 +1,21 @@ --- +- name: alias mysql command to include default options + set_fact: + mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" + +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ diff --git a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml index 51d082e..43eda1a 100644 --- a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml @@ -1,11 +1,21 @@ --- +- name: alias mysql command to include default options + set_fact: + mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" + +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ diff --git a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml index 8c24fc5..da607ce 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml @@ -1,11 +1,21 @@ --- +- name: alias mysql command to include default options + set_fact: + mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" + +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ diff --git a/tests/integration/targets/test_mysql_replication/tasks/main.yml b/tests/integration/targets/test_mysql_replication/tasks/main.yml index 239598a..eae58c0 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/main.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/main.yml @@ -14,6 +14,8 @@ # Tests of channel parameter: - import_tasks: mysql_replication_channel.yml + when: + - install_type == 'mysql' # FIXME: mariadb introduces FOR CHANNEL in 10.7 # Tests of resetmaster mode: - import_tasks: mysql_replication_resetmaster_mode.yml diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml index 55ee6cb..7899e1a 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml @@ -24,14 +24,20 @@ mysql8022_and_higher: true when: - db.version.major > 8 or (db.version.major == 8 and db.version.minor > 0) or (db.version.major == 8 and db.version.minor == 0 and db.version.release >= 22) + - install_type == 'mysql' - name: alias mysql command to include default options set_fact: mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --protocol=tcp" # Preparation: - - name: Create user for replication + - name: Create user for mysql replication shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}" + when: install_type == 'mysql' + + - name: Create user for mariadb replication + shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}" + when: install_type == 'mariadb' - name: Create test database mysql_db: diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml index bb40ec9..437ce81 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml @@ -1,11 +1,17 @@ --- +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ diff --git a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml b/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml index 73cab1b..7bf142e 100644 --- a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml +++ b/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml @@ -167,10 +167,9 @@ tls_requires: - name: retrieve TLS requirements for users - command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" + command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: result - - name: assert user1 TLS requirements assert: that: "'REQUIRE ' not in result.stdout or 'REQUIRE NONE' in result.stdout" diff --git a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml index 3e27eda..dadfb87 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml @@ -1,11 +1,17 @@ --- +- name: set fact tls_enabled + command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" + register: result +- set_fact: + tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}" + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' login_host: 127.0.0.1 login_port: '{{ mysql_primary_port }}' - + when: tls_enabled block: # ============================================================ From 878dc5794a6900e87a51896bbb13116c671217ce Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 16:45:54 +0100 Subject: [PATCH 49/63] Add fixed version of Ubuntu (#470) (#471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is because ubuntu-latest link to ubuntu-22.04 which includes cgroup-v2. I thinks our tests fails because of that. See https://github.com/ansible-collections/news-for-maintainers/issues/28 for more information. (cherry picked from commit 4dac66382a4383b1f2113106e0a43a62946069e4) Co-authored-by: Laurent Indermühle --- .github/workflows/ansible-test-plugins.yml | 6 +++--- .github/workflows/ansible-test-roles.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 4303152..7666117 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -21,7 +21,7 @@ env: jobs: sanity: name: "Sanity (Ansible: ${{ matrix.ansible }})" - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: ansible: @@ -39,7 +39,7 @@ jobs: integration: name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.db_engine_version }}, Connector: ${{ matrix.connector }})" - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: @@ -111,7 +111,7 @@ jobs: testing-type: integration units: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 name: Units (Ⓐ${{ matrix.ansible }}) strategy: # As soon as the first unit test fails, diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index 34bee52..4748b5a 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -14,7 +14,7 @@ on: jobs: molecule: name: "Molecule (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.mysql }})" - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: PY_COLORS: 1 ANSIBLE_FORCE_COLOR: 1 From 43e688a37ade8d516390cddb43d6034b060633ae Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 16:37:56 +0100 Subject: [PATCH 50/63] CI: add PR change detection (#473) (#477) (cherry picked from commit eade7ec1f0aad6de6a6a94e5acb5e9b213c54c2b) Co-authored-by: Andrew Klychkov --- .github/workflows/ansible-test-plugins.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 7666117..af61327 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -25,7 +25,6 @@ jobs: strategy: matrix: ansible: - - stable-2.11 - stable-2.12 - stable-2.13 - stable-2.14 @@ -36,6 +35,7 @@ jobs: with: ansible-core-version: ${{ matrix.ansible }} testing-type: sanity + pull-request-change-detection: true integration: name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.db_engine_version }}, Connector: ${{ matrix.connector }})" @@ -47,7 +47,6 @@ jobs: - mysql_5.7.31 - mysql_8.0.22 ansible: - - stable-2.11 - stable-2.12 - stable-2.13 - stable-2.14 @@ -71,16 +70,12 @@ jobs: ansible: stable-2.14 - python: 3.6 ansible: devel - - python: 3.8 - ansible: stable-2.11 - python: 3.8 ansible: stable-2.13 - python: 3.8 ansible: stable-2.14 - python: 3.8 ansible: devel - - python: 3.9 - ansible: stable-2.11 - python: 3.9 ansible: stable-2.12 steps: @@ -109,6 +104,7 @@ jobs: sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }} target-python-version: ${{ matrix.python }} testing-type: integration + pull-request-change-detection: true units: runs-on: ubuntu-20.04 @@ -119,7 +115,6 @@ jobs: fail-fast: true matrix: ansible: - - stable-2.11 - stable-2.12 - stable-2.13 - stable-2.14 @@ -134,8 +129,6 @@ jobs: ansible: stable-2.14 - python: 3.8 ansible: devel - - python: 3.9 - ansible: stable-2.11 - python: 3.9 ansible: stable-2.12 @@ -148,3 +141,4 @@ jobs: ansible-core-version: ${{ matrix.ansible }} target-python-version: ${{ matrix.python }} testing-type: units + pull-request-change-detection: true From 43a80372326fc9143d9e4e581766813073530653 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Tue, 3 Jan 2023 12:56:33 +0100 Subject: [PATCH 51/63] Docs: change yes/no to true/false (#480) (#482) (cherry picked from commit 3ff1fad5f3e254b0bee18667a7162a1f9c32585c) --- plugins/modules/mysql_db.py | 24 ++++++++++++------------ plugins/modules/mysql_info.py | 10 +++++----- plugins/modules/mysql_query.py | 6 +++--- plugins/modules/mysql_replication.py | 6 +++--- plugins/modules/mysql_user.py | 20 ++++++++++---------- plugins/modules/mysql_variables.py | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/plugins/modules/mysql_db.py b/plugins/modules/mysql_db.py index 1f45e34..965f160 100644 --- a/plugins/modules/mysql_db.py +++ b/plugins/modules/mysql_db.py @@ -53,12 +53,12 @@ options: description: - Execute the dump in a single transaction. type: bool - default: no + default: false quick: description: - Option used for dumping large tables. type: bool - default: yes + default: true ignore_tables: description: - A list of table names that will be ignored in the dump @@ -70,14 +70,14 @@ options: description: - Dump binary columns using hexadecimal notation. type: bool - default: no + default: false version_added: '0.1.0' force: description: - Continue dump or import even if we get an SQL error. - Used only when I(state) is C(dump) or C(import). type: bool - default: no + default: false version_added: '0.1.0' master_data: description: @@ -96,7 +96,7 @@ options: description: - Skip locking tables for read. Used when I(state=dump), ignored otherwise. type: bool - default: no + default: false version_added: '0.1.0' dump_extra_args: description: @@ -110,7 +110,7 @@ options: - If C(yes), the module will internally execute commands via a shell. - Used when I(state=import), ignored otherwise. type: bool - default: no + default: false version_added: '0.1.0' unsafe_login_password: description: @@ -121,7 +121,7 @@ options: - Used only when I(state) is C(import) or C(dump) and I(login_password) is passed, ignored otherwise. type: bool - default: no + default: false version_added: '0.1.0' restrict_config_file: description: @@ -132,14 +132,14 @@ options: under the hood that read named option file in addition to usual option files. - If this behavior is undesirable, use C(yes) to read only named option file. type: bool - default: no + default: false version_added: '0.1.0' check_implicit_admin: description: - Check if mysql allows login as root/nopassword before trying supplied credentials. - If success, passed I(login_user)/I(login_password) will be ignored. type: bool - default: no + default: false version_added: '0.1.0' config_overrides_defaults: description: @@ -148,7 +148,7 @@ options: - Used when I(stat) is C(present) or C(absent), ignored otherwise. - It needs Python 3.5+ as the default interpreter on a target host. type: bool - default: no + default: false version_added: '0.1.0' seealso: @@ -215,7 +215,7 @@ EXAMPLES = r''' name: my_db state: import target: /tmp/dump.sql.bz2 - force: yes + force: true - name: Dump multiple databases community.mysql.mysql_db: @@ -287,7 +287,7 @@ EXAMPLES = r''' - name: Try to create database as root/nopassword first. If not allowed, pass the credentials community.mysql.mysql_db: - check_implicit_admin: yes + check_implicit_admin: true login_user: bob login_password: 123456 name: bobdata diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 1daa9b9..c7761a2 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -42,7 +42,7 @@ options: description: - Includes names of empty databases to returned dictionary. type: bool - default: no + default: false notes: - Calculating the size of a database might be slow, depending on the number and size of tables in it. @@ -96,14 +96,14 @@ EXAMPLES = r''' filter: "!settings,!users" - name: Collect info about databases and version using ~/.my.cnf as a credential file - become: yes + become: true community.mysql.mysql_info: filter: - databases - version - name: Collect info about databases and version using ~alice/.my.cnf as a credential file - become: yes + become: true community.mysql.mysql_info: config_file: /home/alice/.my.cnf filter: @@ -111,13 +111,13 @@ EXAMPLES = r''' - version - name: Collect info about databases including empty and excluding their sizes - become: yes + become: true community.mysql.mysql_info: config_file: /home/alice/.my.cnf filter: - databases exclude_fields: db_size - return_empty_dbs: yes + return_empty_dbs: true ''' RETURN = r''' diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index 04f6201..a3d7ce2 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -27,7 +27,7 @@ options: the state has been changed even if it has not. If it is important in your workflow, use the C(PyMySQL) connector instead. type: raw - required: yes + required: true positional_args: description: - List of values to be passed as positional arguments to the query. @@ -46,7 +46,7 @@ options: description: - Where passed queries run in a single transaction (C(yes)) or commit them one-by-one (C(no)). type: bool - default: no + default: false seealso: - module: community.mysql.mysql_db author: @@ -87,7 +87,7 @@ EXAMPLES = r''' query: - INSERT INTO articles (id, story) VALUES (2, 'my_long_story') - INSERT INTO prices (id, price) VALUES (123, '100.00') - single_transaction: yes + single_transaction: true ''' RETURN = r''' diff --git a/plugins/modules/mysql_replication.py b/plugins/modules/mysql_replication.py index 20f9d6c..df6e539 100644 --- a/plugins/modules/mysql_replication.py +++ b/plugins/modules/mysql_replication.py @@ -167,7 +167,7 @@ options: description: - Fails on error when calling mysql. type: bool - default: False + default: false version_added: '0.1.0' notes: @@ -246,12 +246,12 @@ EXAMPLES = r''' community.mysql.mysql_replication: mode: startreplica connection_name: master-1 - fail_on_error: yes + fail_on_error: true - name: Change master and fail on error (like when replica thread is running) community.mysql.mysql_replication: mode: changemaster - fail_on_error: yes + fail_on_error: true ''' diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index b8e7479..275dde5 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -29,7 +29,7 @@ options: description: - Indicate that the 'password' field is a `mysql_native_password` hash. type: bool - default: no + default: false host: description: - The 'host' part of the MySQL username. @@ -41,7 +41,7 @@ options: to all hostnames for a given user. - This option cannot be used when creating users. type: bool - default: no + default: false priv: description: - "MySQL privileges string in the format: C(db.table:priv1,priv2)." @@ -66,7 +66,7 @@ options: - Append the privileges defined by priv to the existing ones for this user instead of overwriting existing ones. type: bool - default: no + default: false tls_requires: description: - Set requirement for secure transport as a dictionary of requirements (see the examples). @@ -79,7 +79,7 @@ options: description: - Whether binary logging should be enabled or disabled for the connection. type: bool - default: yes + default: true state: description: - Whether the user should exist. @@ -92,7 +92,7 @@ options: - Check if mysql allows login as root/nopassword before trying supplied credentials. - If success, passed I(login_user)/I(login_password) will be ignored. type: bool - default: no + default: false update_password: description: - C(always) will update passwords if they differ. This affects I(password) and the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string). @@ -164,7 +164,7 @@ EXAMPLES = r''' - name: Removes all anonymous user accounts community.mysql.mysql_user: name: '' - host_all: yes + host_all: true state: absent - name: Create database user with name 'bob' and password '12345' with all database privileges @@ -178,7 +178,7 @@ EXAMPLES = r''' community.mysql.mysql_user: name: bob password: '*EE0D72C1085C46C5278932678FBE2C6A782821B4' - encrypted: yes + encrypted: true priv: '*.*:ALL' state: present @@ -249,7 +249,7 @@ EXAMPLES = r''' If mysql allows root/nopassword login, try it without the credentials first. If it's not allowed, pass the credentials community.mysql.mysql_user: - check_implicit_admin: yes + check_implicit_admin: true login_user: root login_password: 123456 name: sally @@ -258,7 +258,7 @@ EXAMPLES = r''' - name: Ensure no user named 'sally' exists at all community.mysql.mysql_user: name: sally - host_all: yes + host_all: true state: absent - name: Specify grants composed of more than one word @@ -290,7 +290,7 @@ EXAMPLES = r''' password: 12345 priv: "*.*:USAGE" state: present - sql_log_bin: no + sql_log_bin: false - name: Create user 'bob' authenticated with plugin 'AWSAuthenticationPlugin' community.mysql.mysql_user: diff --git a/plugins/modules/mysql_variables.py b/plugins/modules/mysql_variables.py index 2544e8d..dc54c82 100644 --- a/plugins/modules/mysql_variables.py +++ b/plugins/modules/mysql_variables.py @@ -22,7 +22,7 @@ options: description: - Variable name to operate. type: str - required: yes + required: true value: description: - If set, then sets variable value to this. From a026d60f84e2d85d718b51886a2ba6a4b6cd5b56 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 13:26:20 +0100 Subject: [PATCH 52/63] README: update Matrix badge (#485) (#487) (cherry picked from commit 4ad71775a6de0223d603d72041d38697afe9a074) Co-authored-by: Andrew Klychkov --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8c2295..d1aa1c3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MySQL collection for Ansible -[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) [![](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20at%20%23mysql:ansible.com&logo=matrix)] +[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) ![](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20on%20Matrix%20%23mysql:ansible.com&logo=matrix) This collection is a part of the Ansible package. From 963e042eddb7165e467eb56ed8e7a0300ec051cc Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Wed, 25 Jan 2023 10:56:39 +0100 Subject: [PATCH 53/63] 491-CI-fix-tarball-download (#491) (#493) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix mariadb test setup * Update mysql src URL * Add changelog fragment * Update 491_fix_download_url.yaml Sanity test failed because minor_changes in not an element of a list. * Fix casing Co-authored-by: Laurent Indermühle (cherry picked from commit 00fa058a18c82e395a1064e7fd7f41d0dc259fdd) Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) --- .github/workflows/ansible-test-plugins.yml | 14 ++++++-------- changelogs/fragments/491_fix_download_url.yaml | 3 +++ .../integration/targets/setup_mysql/vars/main.yml | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 changelogs/fragments/491_fix_download_url.yaml diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index af61327..4622dbe 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -92,14 +92,12 @@ jobs: DB_ENGINE_PRETTY=$([[ "${DB_ENGINE}" == 'mysql' ]] && echo 'MySQL' || echo 'MariaDB'); >&2 echo Matrix factor for the DB is ${{ matrix.db_engine_version }}...; >&2 echo Setting ${DB_ENGINE_PRETTY} version to ${DB_VERSION}...; - sed -i -e "s/^${DB_ENGINE}_version:.*/${DB_ENGINE}_version: $DB_VERSION/g" -e 's/^mariadb_install: false/mariadb_install: true/g' '${{ env.mysql_version_file }}'; - ${{ - matrix.db_engine_version == 'mariadb_10.8.3' - && format( - '>&2 echo Set MariaDB v10.8.3 URL sub dir...; sed -i -e "s/^mariadb_url_subdir:.*/mariadb_url_subdir: linux-systemd/g" "{0}";', env.connector_version_file - ) - || '' - }} + sed -i -e "s/^${DB_ENGINE}_version:.*/${DB_ENGINE}_version: $DB_VERSION/g" '${{ env.mysql_version_file }}'; + if [[ ${{ matrix.db_engine_version }} == mariadb* ]]; + then + echo Set MariaDB install flag...; sed -i -e "s/^mariadb_install: false/mariadb_install: true/g" '${{ env.mysql_version_file }}'; + echo Set MariaDB v10.8.3 URL sub dir...; sed -i -e "s/^mariadb_url_subdir:.*/mariadb_url_subdir: linux-systemd/g" '${{ env.connector_version_file }}'; + fi; >&2 echo Setting Connector version to ${{ matrix.connector }}...; sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }} target-python-version: ${{ matrix.python }} diff --git a/changelogs/fragments/491_fix_download_url.yaml b/changelogs/fragments/491_fix_download_url.yaml new file mode 100644 index 0000000..27628bb --- /dev/null +++ b/changelogs/fragments/491_fix_download_url.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: + - setup_mysql - update MySQL tarball URL (https://github.com/ansible-collections/community.mysql/pull/491). diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml index 4aa52a2..8fbcd90 100644 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ b/tests/integration/targets/setup_mysql/vars/main.yml @@ -24,7 +24,7 @@ install_python_prereqs: - build-essential mysql_tarball: "mysql-{{ mysql_version }}-linux-glibc2.12-x86_64.tar.{{ mysql_compression_extension }}" -mysql_src: "https://dev.mysql.com/get/Downloads/MySQL-{{ mysql_major_version }}/{{ mysql_tarball }}" +mysql_src: "https://cdn.mysql.com/archives/mysql-{{ mysql_major_version }}/{{ mysql_tarball }}" mariadb_url_subdir: "linux" mariadb_tarball: "mariadb-{{ mariadb_version }}-{{ mariadb_url_subdir }}-x86_64.tar.gz" mariadb_src: "https://downloads.mariadb.com/MariaDB/mariadb-{{ mariadb_version }}/bintar-{{ mariadb_url_subdir }}-x86_64/{{ mariadb_tarball }}" From cb323da665f59ceae53c174fe8b087dfeacfaa37 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 26 Jan 2023 09:11:07 +0100 Subject: [PATCH 54/63] README: improve Matrix badge (#494) (#495) * README: improve Matrix badge * Add text (cherry picked from commit 3229ce4e55623453983fa80f0a0ef3109b784543) Co-authored-by: Andrew Klychkov --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1aa1c3..ac6eaea 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MySQL collection for Ansible -[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) ![](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20on%20Matrix%20%23mysql:ansible.com&logo=matrix) +[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) [![Discuss on Matrix at #mysql:ansible.com](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20on%20Matrix%20at%20%23mysql:ansible.com&logo=matrix)](https://matrix.to/#/#mysql:ansible.com) This collection is a part of the Ansible package. From cf25d85e49dbe4f03889d543a5df92c3fe8ac9e4 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 09:47:44 +0100 Subject: [PATCH 55/63] [PR #497/a5f3296d backport][stable-1] mysql_info - Add connector_name and connector_version to returned value (#498) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mysql_info - Add connector_name and connector_version to returned value (#497) * Add methods to retrieve connector name and version * Document that mysqlclient is also named MySQLdb * Document version_added * Add connector name and version in the returned block * Cut condition to display any name that is return In case of MySQLdb is renamed in mysqlclient. In that case, the integration tests will catch this the day we update the connector version. Co-authored-by: Andrew Klychkov (cherry picked from commit a5f3296d731bef582199300d8d296a8f8476c4a2) * Cut fragment not relevant to the collection usage * Updated version_added for stable-1 --------- Co-authored-by: Laurent Indermühle --- .../fragments/491_fix_download_url.yaml | 3 -- ...nfo_returns_connector_name_and_version.yml | 3 ++ plugins/module_utils/mysql.py | 38 +++++++++++++++++++ plugins/modules/mysql_info.py | 32 ++++++++++++++-- .../test_mysql_info/tasks/connector_info.yml | 32 ++++++++++++++++ .../targets/test_mysql_info/tasks/main.yml | 4 ++ 6 files changed, 106 insertions(+), 6 deletions(-) delete mode 100644 changelogs/fragments/491_fix_download_url.yaml create mode 100644 changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml create mode 100644 tests/integration/targets/test_mysql_info/tasks/connector_info.yml diff --git a/changelogs/fragments/491_fix_download_url.yaml b/changelogs/fragments/491_fix_download_url.yaml deleted file mode 100644 index 27628bb..0000000 --- a/changelogs/fragments/491_fix_download_url.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - setup_mysql - update MySQL tarball URL (https://github.com/ansible-collections/community.mysql/pull/491). diff --git a/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml b/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml new file mode 100644 index 0000000..11fc4f5 --- /dev/null +++ b/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - mysql_info - add ``connector_name`` and ``connector_version`` to returned values (https://github.com/ansible-collections/community.mysql/pull/497). diff --git a/plugins/module_utils/mysql.py b/plugins/module_utils/mysql.py index d256599..b206fcc 100644 --- a/plugins/module_utils/mysql.py +++ b/plugins/module_utils/mysql.py @@ -23,6 +23,7 @@ try: _mysql_cursor_param = 'cursor' except ImportError: try: + # mysqlclient is called MySQLdb import MySQLdb as mysql_driver import MySQLdb.cursors _mysql_cursor_param = 'cursorclass' @@ -35,6 +36,43 @@ mysql_driver_fail_msg = ('A MySQL module is required: for Python 2.7 either PyMy 'the intended Python version.') +def get_connector_name(connector): + """ (class) -> str + Return the name of the connector (pymysql or mysqlclient (MySQLdb)) + or 'Unknown' if not pymysql or MySQLdb. When adding a + connector here, also modify get_connector_version. + """ + if connector is None or not hasattr(connector, '__name__'): + return 'Unknown' + + return connector.__name__ + + +def get_connector_version(connector): + """ (class) -> str + Return the version of pymysql or mysqlclient (MySQLdb). + Return 'Unknown' if the connector name is unknown. + """ + + if connector is None: + return 'Unknown' + + connector_name = get_connector_name(connector) + + if connector_name == 'pymysql': + # pymysql has two methods: + # - __version__ that returns the string: 0.7.11.None + # - VERSION that returns the tuple (0, 7, 11, None) + v = connector.VERSION[:3] + return '.'.join(map(str, v)) + elif connector_name == 'MySQLdb': + # version_info returns the tuple (2, 1, 1, 'final', 0) + v = connector.version_info[:3] + return '.'.join(map(str, v)) + else: + return 'Unknown' + + def parse_from_mysql_config_file(cnf): # Default values of comment_prefix is '#' and ';'. # '!' added to prevent a parsing error diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index c7761a2..bc7c076 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -58,6 +58,7 @@ seealso: author: - Andrew Klychkov (@Andersson007) - Sebastian Gumprich (@rndmh3ro) +- Laurent Indermühle (@laurent-indermuehle) extends_documentation_fragment: - community.mysql.mysql @@ -206,6 +207,21 @@ slave_hosts: type: dict sample: - { "2": { "Host": "", "Master_id": 1, "Port": 3306 } } +connector_name: + description: Name of the python connector used by the module. When the connector is not identified, returns C(Unknown). + returned: always + type: str + sample: + - "pymysql" + - "MySQLdb" + version_added: '1.5.0' +connector_version: + description: Version of the python connector used by the module. When the connector is not identified, returns C(Unknown). + returned: always + type: str + sample: + - "1.0.2" + version_added: '1.5.0' ''' from decimal import Decimal @@ -216,6 +232,8 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import ( mysql_common_argument_spec, mysql_driver, mysql_driver_fail_msg, + get_connector_name, + get_connector_version, ) from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native @@ -558,21 +576,29 @@ def main(): if mysql_driver is None: module.fail_json(msg=mysql_driver_fail_msg) + connector_name = get_connector_name(mysql_driver) + connector_version = get_connector_version(mysql_driver) + try: cursor, db_conn = mysql_connect(module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, db, check_hostname=check_hostname, connect_timeout=connect_timeout, cursor_class='DictCursor') except Exception as e: - module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. " - "Exception message: %s" % (config_file, to_native(e))) + msg = ('unable to connect to database using %s %s, check login_user ' + 'and login_password are correct or %s has the credentials. ' + 'Exception message: %s' % (connector_name, connector_version, config_file, to_native(e))) + module.fail_json(msg) ############################### # Create object and do main job mysql = MySQL_Info(module, cursor) - module.exit_json(changed=False, **mysql.get_info(filter_, exclude_fields, return_empty_dbs)) + module.exit_json(changed=False, + connector_name=connector_name, + connector_version=connector_version, + **mysql.get_info(filter_, exclude_fields, return_empty_dbs)) if __name__ == '__main__': diff --git a/tests/integration/targets/test_mysql_info/tasks/connector_info.yml b/tests/integration/targets/test_mysql_info/tasks/connector_info.yml new file mode 100644 index 0000000..349ccef --- /dev/null +++ b/tests/integration/targets/test_mysql_info/tasks/connector_info.yml @@ -0,0 +1,32 @@ +--- +# Added in 1.5.0, 2.4.0 and 3.6.0 in +# https://github.com/ansible-collections/community.mysql/pull/497 + +# TODO: Refactor in PR490. +- name: Connector info | Assert connector_name exists and has expected values + ansible.builtin.assert: + that: + - result.connector_name is defined + - result.connector_name is in ['pymysql', 'MySQLdb'] + success_msg: >- + Assertions passed, result.connector_name is {{ result.connector_name }} + fail_msg: >- + Assertion failed, result.connector_name is + {{ result.connector_name | d('Unknown')}} which is different than expected + pymysql or MySQLdb + +# TODO: Refactor in PR490. +- name: Connector info | Assert connector_version exists and has expected values + ansible.builtin.assert: + that: + - result.connector_version is defined + - > + result.connector_version == 'Unknown' + or result.connector_version is version(connector_ver, '==') + success_msg: >- + Assertions passed, result.connector_version is + {{ result.connector_version }} + fail_msg: >- + Assertion failed, result.connector_version is + {{ result.connector_version }} which is different than expected + {{ connector_ver }} diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index ec2bd9b..a5428e3 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -55,6 +55,10 @@ - result.engines != {} - result.users != {} + - name: mysql_info - Test connector informations display + ansible.builtin.import_tasks: + file: connector_info.yml + # Access by non-default cred file - name: mysql_info - check non-default cred file mysql_info: From 8687e575d75a0e076358c1977aa4fb9df5a7df36 Mon Sep 17 00:00:00 2001 From: Markus Bergholz Date: Wed, 8 Feb 2023 10:34:27 +0100 Subject: [PATCH 56/63] prepare community.mysql 1.5.0 (#505) * prepare 1.4.10 * 1.5.0 --- CHANGELOG.rst | 15 +++++++++++++++ changelogs/changelog.yaml | 15 +++++++++++++++ ...ql_info_returns_connector_name_and_version.yml | 3 --- changelogs/fragments/backport-stable-2-pr-452.yml | 4 ---- galaxy.yml | 2 +- 5 files changed, 31 insertions(+), 8 deletions(-) delete mode 100644 changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml delete mode 100644 changelogs/fragments/backport-stable-2-pr-452.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 112b294..da8e743 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,21 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.5.0 +======= + +Release Summary +--------------- + +This is a minor release of the ``community.mysql`` collection. +This changelog contains all changes to the modules and plugins in this collection +that have been made after the previous release. + +Minor Changes +------------- + +- mysql_info - add ``connector_name`` and ``connector_version`` to returned values (https://github.com/ansible-collections/community.mysql/pull/497). + v1.4.8 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index b24e587..1d4368d 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -395,3 +395,18 @@ releases: - 1.4.8.yml - simplified-bsd-license.yml release_date: '2022-07-28' + 1.5.0: + changes: + minor_changes: + - mysql_info - add ``connector_name`` and ``connector_version`` to returned + values (https://github.com/ansible-collections/community.mysql/pull/497). + release_summary: 'This is bugfix release of the ``community.mysql`` collection. + + This changelog contains all changes to the modules and plugins in this collection + + that have been made after the previous release.' + fragments: + - 1.5.0.yml + - 497_mysql_info_returns_connector_name_and_version.yml + - backport-stable-2-pr-452.yml + release_date: '2023-02-08' \ No newline at end of file diff --git a/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml b/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml deleted file mode 100644 index 11fc4f5..0000000 --- a/changelogs/fragments/497_mysql_info_returns_connector_name_and_version.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - mysql_info - add ``connector_name`` and ``connector_version`` to returned values (https://github.com/ansible-collections/community.mysql/pull/497). diff --git a/changelogs/fragments/backport-stable-2-pr-452.yml b/changelogs/fragments/backport-stable-2-pr-452.yml deleted file mode 100644 index ee84ae2..0000000 --- a/changelogs/fragments/backport-stable-2-pr-452.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- - -trivial: - - Tests - Backport PR-452 Sync GHA workflow w/ the collection template diff --git a/galaxy.yml b/galaxy.yml index ee76d66..289ddf9 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,6 @@ namespace: community name: mysql -version: 1.4.9 +version: 1.5.0 readme: README.md authors: - Ansible community From 62e2ed5d36b04336df54e8b030b769e66c6bf516 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:59:16 +0100 Subject: [PATCH 57/63] [PR #508/9b8455c2 backport][stable-1] Fix sanity (#510) * Fix sanity (#508) * Fix sanity * Remove as unnecessary (cherry picked from commit 9b8455c2e66aebd2e0adeb544450749876d7537d) * Update tests/unit/plugins/modules/test_mysql_user.py --------- Co-authored-by: Andrew Klychkov --- plugins/modules/mysql_replication.py | 1 - tests/sanity/ignore-2.10.txt | 8 -------- tests/sanity/ignore-2.11.txt | 8 -------- tests/sanity/ignore-2.15.txt | 2 ++ tests/sanity/ignore-2.9.txt | 3 --- tests/unit/plugins/modules/test_mysql_user.py | 2 -- 6 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 tests/sanity/ignore-2.10.txt delete mode 100644 tests/sanity/ignore-2.11.txt delete mode 100644 tests/sanity/ignore-2.9.txt diff --git a/plugins/modules/mysql_replication.py b/plugins/modules/mysql_replication.py index df6e539..011c279 100644 --- a/plugins/modules/mysql_replication.py +++ b/plugins/modules/mysql_replication.py @@ -275,7 +275,6 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import ( mysql_common_argument_spec, ) from ansible.module_utils._text import to_native -from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion executed_queries = [] diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt deleted file mode 100644 index c0323af..0000000 --- a/tests/sanity/ignore-2.10.txt +++ /dev/null @@ -1,8 +0,0 @@ -plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch -plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen -plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch -plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_user.py validate-modules:undocumented-parameter -plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt deleted file mode 100644 index c0323af..0000000 --- a/tests/sanity/ignore-2.11.txt +++ /dev/null @@ -1,8 +0,0 @@ -plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch -plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen -plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch -plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements -plugins/modules/mysql_user.py validate-modules:undocumented-parameter -plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt index c0323af..da0354c 100644 --- a/tests/sanity/ignore-2.15.txt +++ b/tests/sanity/ignore-2.15.txt @@ -6,3 +6,5 @@ plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements plugins/modules/mysql_user.py validate-modules:undocumented-parameter plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch +plugins/module_utils/mysql.py pylint:unused-import +plugins/module_utils/version.py pylint:unused-import diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt deleted file mode 100644 index dabd55d..0000000 --- a/tests/sanity/ignore-2.9.txt +++ /dev/null @@ -1,3 +0,0 @@ -plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen -plugins/modules/mysql_user.py validate-modules:parameter-type-not-in-doc -plugins/modules/mysql_user.py validate-modules:undocumented-parameter diff --git a/tests/unit/plugins/modules/test_mysql_user.py b/tests/unit/plugins/modules/test_mysql_user.py index 3b88e24..cf5bd3c 100644 --- a/tests/unit/plugins/modules/test_mysql_user.py +++ b/tests/unit/plugins/modules/test_mysql_user.py @@ -8,7 +8,6 @@ try: from unittest.mock import MagicMock except ImportError: from mock import MagicMock - from ansible_collections.community.mysql.plugins.modules.mysql_user import ( handle_grant_on_col, has_grant_on_col, @@ -16,7 +15,6 @@ from ansible_collections.community.mysql.plugins.modules.mysql_user import ( sort_column_order, handle_requiressl_in_priv_string ) -from ..utils import dummy_cursor_class @pytest.mark.parametrize( From 54efe0bbb87e863c2f4f003bc546c38b1faa509e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Wed, 29 Mar 2023 08:56:09 +0200 Subject: [PATCH 58/63] [PR #490/6970aef backport][stable-1] Integrations tests : Use containers (#517) * Integrations tests : Use containers for more control and verify that versions match expectation (#490) * Add healthcheck to MariaDB before starting the tests This prevent the first test to fail because the db isn't ready yet. * Add % instead of the default 'localhost' since we use remote connection Previously, everything was on localhost. Now ansible-test is in a venv and the db is in a container. The db see the IP address from the podman host (10.88.0.2) * Add mysql_client to the controller * Prepare controller with Podman/Docker Network We use the Podman/Docker network gateway address to communicate between container. I haven't tested Docker. I would have preferred to use a pod but only Podman support it and ansible-test only support the --docker-network option. * Generalize mysql and mariadb version based on container name This way we can split db_engine and db_version and simplify tests. Also this is mandatory to use the matrix.db_engine_version as the image name for our services containers. * Fix replication due to usage of gateway_addr instead of localhost * Refactor setup_mysql into setup_controller * Fix server_id in GHA GHA lack a way to pass option to docker's command. Also server_id is not read as a environment variable. So I'm forced to use a config file. * Refactor test_mysql_user to work with other host than localhost * Refactor way tests info are passed from sed to file with lookup The idea is to avoid modifying test targets from the workflow to prevent ansible-test to think every tests needs to be run. * Refactor test to use the db_version from setup_controller * Add temporary files to .gitignore * Add back docker healthcheck on services I saw in the GHA logs that it perform an healtcheck ! So I hope this will work. * Refactor the way server_id is set for replicas The simple way is to add '--server-id 2' after the name of the image of the container. But GHA doesn't let us do that. The idea of mount a file from our repo doesn't work because the repo is check out later in the workflow and I failed to find a pre-job hook. Then I realized that this MySQL option is dynamic! So we will set that in the test target! * Add IF NOT EXISTS to prevent misleading error on retry * Cut python 3.11 not supported by ansible-test yet * Add option to run only a single target * Disable replication with channel tests entirely for MySQL 5.7 * Activate Mysql 8 and Mariadb into GitHub Action Workflow * Document run_all_tests.py * Fix replication settings sh don't know 'echo -e', so we use bash instead. Also, we need to wait for the container to be healthy before trying to restart it. Otherwise that could corrupt it. * Add more descriptive tests names * Use mysql_host var name instead of gateway_addr in tests * Refactor user@ into user@% * Workaround for plugin role that fails with any MariaDB versions * Ensure replicas are healthy before rebooting them * Add a virtualenv for ansible-test used locally * Cut column-statistics disabling Thanks to our test-container, we now use the correspond mysql-client. So to test mysql 5.7 we use mysql-client-5.7 and to test mysql 8 we use mysql-client-8. * Fix test matrix Python version should be quoted, otherwise 3.10 become 3.1 We can skip 2.14 and devel with Python3.8 We can skip devel with Python 3.9 We can skip MariaDB 10.4 with mysql-client-10.6 Add tests for MariaDB 10.6, 10.7 and 10.8 * Fix queries for roles * Add filter for issues resolved in newer version of mysqlclient * Add names to tests * Cut tests for incompatible MySQL 8 and pymysql 0.7.11 * Fix assertion for older mysqlclient than 2.0.1 with mysql (mariadb ok) * Change docker-image workflow to work on all images using matrix * Add support for version of mysqlclient * Fix verify database version Sometimes, version_full contains trailing information (-log). To prevent issues it's best to concatenate major and minor version. * Cut filter for tests now that the right connector is used * Add clean up in "always" phase of the block Because our tests use --retry-on-error, and the first thing the test does is to try to create the database. We must cleanup otherwise if there is a retry, it will throw a misleading "database already exists" error. * Disable tests using pymysql 1.0.2 Many tests are failing but this must be fixed in the plugins in a future PR. * Cut test MySQL 8 with incompatible pymysql 0.7.11 It fails to connect with error about cryptography unsupported * Fix missing cffi package to connect to MySQL 8 using Python 3.9 * Split Docker image workflow to rebuild only changed Dockerfile My goal is not to save the planet but to make it work. Currently docker/setup-buildx-action@v2 often fails. You have to rerun the workflow multiple times until it succeed. When you do that with the matrix with 15 containers, you never get to the point where they all built successfully. Having separate workflows makes rerun the failing build easier. * Add option to let containers alive at end of testing * Migrate tests documentations in their own file * Document usage of continue_on_errors * Add support for systems with unsupported python set as default * Add create podman network for system missing it. We saw that on a Fedora 33 with Podman 3.3.1, an old system. I didn't find in which release the default network changed and maybe it's defined in the Linux distribution. So in doubt I always attempt to create the network. * Add full path to image to prevent podman asking which registry to use * Add options to enforce recreate containers even if already exists * Add deletion of anonymous volumes associated with the container * Change shebang from python to python3 to avoid confusion with python2 This script is a python3 script. * Add disk and RAM requirements * Cut the 3 from python command to follow shebang recommendations https://docs.ansible.com/ansible-core/devel/dev_guide/testing/sanity/shebang.html * Reformat file path Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Move utility task files in their own folder * Add called workflow file in the GHA hooks Without this, the containers are not rebuilt when you modify the file built-docker-image.yml. * Rollback to github.repository in container image name This time I think I understood. We publish in the github.repository_owner's namespace. In my case it's laurent-indermuehle and in case of upstream it's ansible-collections. A proof of that: https://github.com/orgs/ansible-collections/packages <- here there is one attempt I did in february to push my branch to the upstream. So, our tests containers will be visible to the whole community, not just community.mysql. --------- Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) (cherry picked from commit 6970aef8f61373e9f85cb6f251b3b44decb7c496) * Add changelog fragment * Disable tests that doesn't work on stable-1 It's shameful to disable tests, but they didn't makes much sense anyway. * Fix error message being different on stable-1 than v3 * Disable tests against MariaDB 10.5 and 10.6 Does version have never been tested on stable-1 and many tests fails. --- .github/workflows/ansible-test-plugins.yml | 376 +++++++++++++++--- .github/workflows/ansible-test-roles.yml | 1 + .github/workflows/build-docker-image.yml | 67 ++++ ...r-image-mariadb103-py38-mysqlclient201.yml | 19 + ...ocker-image-mariadb103-py38-pymysql093.yml | 19 + ...r-image-mariadb103-py39-mysqlclient203.yml | 19 + ...ocker-image-mariadb103-py39-pymysql093.yml | 19 + ...-image-mariadb106-py310-mysqlclient211.yml | 19 + ...cker-image-mariadb106-py310-pymysql102.yml | 19 + .../docker-image-my57-py38-mysqlclient201.yml | 19 + .../docker-image-my57-py38-pymysql0711.yml | 19 + .../docker-image-my57-py38-pymysql093.yml | 19 + ...docker-image-my80-py310-mysqlclient211.yml | 19 + .../docker-image-my80-py310-pymysql102.yml | 19 + .../docker-image-my80-py38-mysqlclient201.yml | 19 + .../docker-image-my80-py38-pymysql093.yml | 19 + .../docker-image-my80-py39-mysqlclient203.yml | 19 + .../docker-image-my80-py39-pymysql093.yml | 19 + .gitignore | 1 + Makefile | 80 ++++ README.md | 21 +- TESTING.md | 87 ++++ .../490_refactor_integration_tests.yml | 6 + .../fragments/backport-stable-1-pr-490.yml | 3 + run_all_tests.py | 86 ++++ .../mariadb103-py38-mysqlclient201/Dockerfile | 21 + .../mariadb103-py38-pymysql093/Dockerfile | 15 + .../mariadb103-py39-mysqlclient203/Dockerfile | 21 + .../mariadb103-py39-pymysql093/Dockerfile | 15 + .../Dockerfile | 21 + .../mariadb106-py310-pymysql102/Dockerfile | 15 + .../my57-py38-mysqlclient201/Dockerfile | 21 + .../my57-py38-pymysql0711/Dockerfile | 21 + .../my57-py38-pymysql093/Dockerfile | 15 + .../my80-py310-mysqlclient211/Dockerfile | 21 + .../my80-py310-pymysql102/Dockerfile | 15 + .../my80-py38-mysqlclient201/Dockerfile | 21 + .../my80-py38-pymysql093/Dockerfile | 15 + .../my80-py39-mysqlclient203/Dockerfile | 21 + .../my80-py39-pymysql093/Dockerfile | 16 + .../old_mariadb_replication/defaults/main.yml | 2 + .../tasks/mariadb_master_use_gtid.yml | 36 +- .../mariadb_replication_connection_name.yml | 22 +- .../tasks/mariadb_replication_initial.yml | 20 +- .../setup_controller/tasks/fake_root.yml | 11 + .../targets/setup_controller/tasks/main.yml | 18 + .../setup_controller/tasks/setvars.yml | 69 ++++ .../targets/setup_controller/tasks/verify.yml | 59 +++ .../targets/setup_mysql/defaults/main.yml | 18 - .../targets/setup_mysql/handlers/main.yml | 6 - .../targets/setup_mysql/tasks/config.yml | 15 - .../targets/setup_mysql/tasks/dir.yml | 11 - .../targets/setup_mysql/tasks/install.yml | 90 ----- .../targets/setup_mysql/tasks/main.yml | 11 - .../targets/setup_mysql/tasks/setvars.yml | 33 -- .../targets/setup_mysql/tasks/verify.yml | 27 -- .../setup_mysql/templates/installed_file.j2 | 1 - .../targets/setup_mysql/vars/main.yml | 30 -- .../targets/test_mysql_db/defaults/main.yml | 1 + .../targets/test_mysql_db/meta/main.yml | 2 +- .../tasks/config_overrides_defaults.yml | 73 ++-- .../tasks/encoding_dump_import.yml | 52 +-- .../targets/test_mysql_db/tasks/issue-28.yml | 16 +- .../tasks/issue_256_mysqldump_errors.yml | 0 .../targets/test_mysql_db/tasks/main.yml | 5 +- .../tasks/multi_db_create_delete.yml | 45 ++- .../test_mysql_db/tasks/state_dump_import.yml | 199 +++++---- .../tasks/state_present_absent.yml | 108 ++--- .../targets/test_mysql_info/defaults/main.yml | 2 +- .../targets/test_mysql_info/meta/main.yml | 3 +- .../test_mysql_info/tasks/connector_info.yml | 6 +- .../test_mysql_info/tasks/issue-28.yml | 19 +- .../targets/test_mysql_info/tasks/main.yml | 28 +- .../test_mysql_query/defaults/main.yml | 1 + .../targets/test_mysql_query/meta/main.yml | 3 +- .../test_mysql_query/tasks/issue-28.yml | 19 +- .../tasks/mysql_query_initial.yml | 99 +++-- .../test_mysql_replication/defaults/main.yml | 2 +- .../test_mysql_replication/meta/main.yml | 2 +- .../tasks/issue-265.yml | 0 .../test_mysql_replication/tasks/issue-28.yml | 18 +- .../test_mysql_replication/tasks/main.yml | 3 +- .../tasks/mysql_replication_channel.yml | 3 +- .../tasks/mysql_replication_initial.yml | 127 +++--- .../tasks/mysql_replication_master_delay.yml | 2 +- .../mysql_replication_resetmaster_mode.yml | 2 +- .../targets/test_mysql_user/defaults/main.yml | 2 +- .../targets/test_mysql_user/meta/main.yml | 3 +- .../test_mysql_user/tasks/assert_no_user.yml | 25 -- .../test_mysql_user/tasks/assert_user.yml | 38 -- .../test_mysql_user/tasks/create_user.yml | 40 -- .../test_mysql_user/tasks/issue-121.yml | 135 +++---- .../test_mysql_user/tasks/issue-265.yml | 0 .../test_mysql_user/tasks/issue-28.yml | 52 +-- .../test_mysql_user/tasks/issue-29511.yaml | 30 +- .../test_mysql_user/tasks/issue-64560.yaml | 19 +- .../targets/test_mysql_user/tasks/main.yml | 132 ++---- .../test_mysql_user/tasks/remove_user.yml | 74 ---- .../tasks/test_idempotency.yml | 84 ++++ .../tasks/test_priv_append.yml | 74 ++-- .../test_mysql_user/tasks/test_priv_dict.yml | 80 ++-- .../tasks/test_priv_subtract.yml | 0 .../test_mysql_user/tasks/test_privs.yml | 137 +++++-- .../tasks/test_privs_issue_465.yml | 31 ++ ...ce_limits.yml => test_resource_limits.yml} | 54 ++- .../tasks/test_revoke_only_grant.yml | 50 +++ ...irements.yml => test_tls_requirements.yml} | 98 +++-- .../tasks/test_update_password.yml | 129 ++++++ .../test_user_grants_with_roles_applied.yml | 47 +-- .../tasks/test_user_password.yml | 110 ++--- .../tasks/test_user_plugin_auth.yml | 233 +++++------ .../tasks/utils/assert_no_user.yml | 8 + .../tasks/utils/assert_user.yml | 21 + .../{ => utils}/assert_user_password.yml | 12 +- .../tasks/utils/create_user.yml | 12 + .../tasks/utils/remove_user.yml | 12 + .../test_mysql_variables/defaults/main.yml | 1 + .../test_mysql_variables/meta/main.yml | 3 +- .../test_mysql_variables/tasks/assert_var.yml | 7 +- .../test_mysql_variables/tasks/issue-28.yml | 16 +- .../tasks/mysql_variables.yml | 23 +- tests/integration/test_connection.yml | 81 ++++ 122 files changed, 2960 insertions(+), 1519 deletions(-) create mode 100644 .github/workflows/build-docker-image.yml create mode 100644 .github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml create mode 100644 .github/workflows/docker-image-mariadb103-py38-pymysql093.yml create mode 100644 .github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml create mode 100644 .github/workflows/docker-image-mariadb103-py39-pymysql093.yml create mode 100644 .github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml create mode 100644 .github/workflows/docker-image-mariadb106-py310-pymysql102.yml create mode 100644 .github/workflows/docker-image-my57-py38-mysqlclient201.yml create mode 100644 .github/workflows/docker-image-my57-py38-pymysql0711.yml create mode 100644 .github/workflows/docker-image-my57-py38-pymysql093.yml create mode 100644 .github/workflows/docker-image-my80-py310-mysqlclient211.yml create mode 100644 .github/workflows/docker-image-my80-py310-pymysql102.yml create mode 100644 .github/workflows/docker-image-my80-py38-mysqlclient201.yml create mode 100644 .github/workflows/docker-image-my80-py38-pymysql093.yml create mode 100644 .github/workflows/docker-image-my80-py39-mysqlclient203.yml create mode 100644 .github/workflows/docker-image-my80-py39-pymysql093.yml create mode 100644 Makefile create mode 100644 TESTING.md create mode 100644 changelogs/fragments/490_refactor_integration_tests.yml create mode 100644 changelogs/fragments/backport-stable-1-pr-490.yml create mode 100755 run_all_tests.py create mode 100644 test-containers/mariadb103-py38-mysqlclient201/Dockerfile create mode 100644 test-containers/mariadb103-py38-pymysql093/Dockerfile create mode 100644 test-containers/mariadb103-py39-mysqlclient203/Dockerfile create mode 100644 test-containers/mariadb103-py39-pymysql093/Dockerfile create mode 100644 test-containers/mariadb106-py310-mysqlclient211/Dockerfile create mode 100644 test-containers/mariadb106-py310-pymysql102/Dockerfile create mode 100644 test-containers/my57-py38-mysqlclient201/Dockerfile create mode 100644 test-containers/my57-py38-pymysql0711/Dockerfile create mode 100644 test-containers/my57-py38-pymysql093/Dockerfile create mode 100644 test-containers/my80-py310-mysqlclient211/Dockerfile create mode 100644 test-containers/my80-py310-pymysql102/Dockerfile create mode 100644 test-containers/my80-py38-mysqlclient201/Dockerfile create mode 100644 test-containers/my80-py38-pymysql093/Dockerfile create mode 100644 test-containers/my80-py39-mysqlclient203/Dockerfile create mode 100644 test-containers/my80-py39-pymysql093/Dockerfile create mode 100644 tests/integration/targets/setup_controller/tasks/fake_root.yml create mode 100644 tests/integration/targets/setup_controller/tasks/main.yml create mode 100644 tests/integration/targets/setup_controller/tasks/setvars.yml create mode 100644 tests/integration/targets/setup_controller/tasks/verify.yml delete mode 100644 tests/integration/targets/setup_mysql/defaults/main.yml delete mode 100644 tests/integration/targets/setup_mysql/handlers/main.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/config.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/dir.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/install.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/main.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/setvars.yml delete mode 100644 tests/integration/targets/setup_mysql/tasks/verify.yml delete mode 100644 tests/integration/targets/setup_mysql/templates/installed_file.j2 delete mode 100644 tests/integration/targets/setup_mysql/vars/main.yml create mode 100644 tests/integration/targets/test_mysql_db/tasks/issue_256_mysqldump_errors.yml create mode 100644 tests/integration/targets/test_mysql_replication/tasks/issue-265.yml delete mode 100644 tests/integration/targets/test_mysql_user/tasks/assert_no_user.yml delete mode 100644 tests/integration/targets/test_mysql_user/tasks/assert_user.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/issue-265.yml delete mode 100644 tests/integration/targets/test_mysql_user/tasks/remove_user.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_idempotency.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_priv_subtract.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_privs_issue_465.yml rename tests/integration/targets/test_mysql_user/tasks/{resource_limits.yml => test_resource_limits.yml} (60%) create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml rename tests/integration/targets/test_mysql_user/tasks/{tls_requirements.yml => test_tls_requirements.yml} (57%) create mode 100644 tests/integration/targets/test_mysql_user/tasks/test_update_password.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/utils/assert_no_user.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/utils/assert_user.yml rename tests/integration/targets/test_mysql_user/tasks/{ => utils}/assert_user_password.yml (73%) create mode 100644 tests/integration/targets/test_mysql_user/tasks/utils/create_user.yml create mode 100644 tests/integration/targets/test_mysql_user/tasks/utils/remove_user.yml create mode 100644 tests/integration/test_connection.yml diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 4622dbe..88d8fce 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -1,3 +1,4 @@ +--- name: Plugins CI on: push: @@ -14,10 +15,6 @@ on: - cron: '0 6 * * *' -env: - mysql_version_file: "tests/integration/targets/setup_mysql/defaults/main.yml" - connector_version_file: "tests/integration/targets/setup_mysql/vars/main.yml" - jobs: sanity: name: "Sanity (Ansible: ${{ matrix.ansible }})" @@ -43,42 +40,312 @@ jobs: strategy: fail-fast: false matrix: - db_engine_version: - - mysql_5.7.31 - - mysql_8.0.22 - ansible: - - stable-2.12 - - stable-2.13 - - stable-2.14 - - devel - python: - - 3.6 - - 3.8 - - 3.9 - connector: - - pymysql==0.7.10 - - pymysql==0.9.3 - - mysqlclient==2.0.1 - exclude: - - db_engine_version: mysql_8.0.22 - connector: pymysql==0.7.10 - - python: 3.6 - ansible: stable-2.12 - - python: 3.6 - ansible: stable-2.13 - - python: 3.6 - ansible: stable-2.14 - - python: 3.6 - ansible: devel - - python: 3.8 - ansible: stable-2.13 - - python: 3.8 - ansible: stable-2.14 - - python: 3.8 - ansible: devel - - python: 3.9 - ansible: stable-2.12 + include: + # Before we can activate test with pymysql 1.0.2 we should debug the + # following plugins: + # + # mysql_query: + # test "Assert that create table IF NOT EXISTS is not changed with pymysql" failed + # + # mysql_replication: + # test "Assert that startreplica is not changed" failed + + # ================================================================== + # mysql-client 5.7 + Python 3.8 + # ================================================================== + - ansible: stable-2.12 + db_engine_version: mysql:5.7.40 + python: '3.8' + connector: pymysql==0.7.11 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-pymysql0711:latest + - ansible: stable-2.12 + db_engine_version: mysql:5.7.40 + python: '3.8' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-pymysql093:latest + - ansible: stable-2.12 + db_engine_version: mysql:5.7.40 + python: '3.8' + connector: mysqlclient==2.0.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-mysqlclient201:latest + + + # ================================================================== + # mysql-client 8 + Python 3.8 + # ================================================================== + - ansible: stable-2.12 + db_engine_version: mysql:8.0.31 + python: '3.8' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py38-pymysql093:latest + - ansible: stable-2.12 + db_engine_version: mysql:8.0.31 + python: '3.8' + connector: mysqlclient==2.0.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py38-mysqlclient201:latest + + + # ================================================================== + # mysql-client 8 + Python 3.9 + # ================================================================== + - ansible: stable-2.13 + db_engine_version: mysql:8.0.31 + python: '3.9' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-pymysql093:latest + - ansible: stable-2.13 + db_engine_version: mysql:8.0.31 + python: '3.9' + connector: mysqlclient==2.0.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-mysqlclient203:latest + + - ansible: stable-2.14 + db_engine_version: mysql:8.0.31 + python: '3.9' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-pymysql093:latest + - ansible: stable-2.14 + db_engine_version: mysql:8.0.31 + python: '3.9' + connector: mysqlclient==2.0.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-mysqlclient203:latest + + + # ================================================================== + # mysql-client 8 + Python 3.10 + # ================================================================== + # - ansible: stable-2.13 + # db_engine_version: mysql:8.0.31 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest + - ansible: stable-2.13 + db_engine_version: mysql:8.0.31 + python: '3.10' + connector: mysqlclient==2.1.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest + + # - ansible: stable-2.14 + # db_engine_version: mysql:8.0.31 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest + - ansible: stable-2.14 + db_engine_version: mysql:8.0.31 + python: '3.10' + connector: mysqlclient==2.1.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest + + # - ansible: devel + # db_engine_version: mysql:8.0.31 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest + - ansible: devel + db_engine_version: mysql:8.0.31 + python: '3.10' + connector: mysqlclient==2.1.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest + + # ================================================================== + # mariadb-client 10.3 + Python 3.8 + # ================================================================== + - ansible: stable-2.12 + db_engine_version: mariadb:10.4.27 + python: '3.8' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-pymysql093:latest + - ansible: stable-2.12 + db_engine_version: mariadb:10.4.27 + python: '3.8' + connector: mysqlclient==2.0.1 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-mysqlclient201:latest + # - ansible: stable-2.12 + # db_engine_version: mariadb:10.5.18 + # python: '3.8' + # connector: pymysql==0.9.3 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-pymysql093:latest + # - ansible: stable-2.12 + # db_engine_version: mariadb:10.5.18 + # python: '3.8' + # connector: mysqlclient==2.0.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-mysqlclient201:latest + + + # ================================================================== + # mariadb-client 10.3 + Python 3.9 + # ================================================================== + - ansible: stable-2.13 + db_engine_version: mariadb:10.4.27 + python: '3.9' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest + - ansible: stable-2.13 + db_engine_version: mariadb:10.4.27 + python: '3.9' + connector: mysqlclient==2.0.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.5.18 + # python: '3.9' + # connector: pymysql==0.9.3 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.5.18 + # python: '3.9' + # connector: mysqlclient==2.0.3 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest + + - ansible: stable-2.14 + db_engine_version: mariadb:10.4.27 + python: '3.9' + connector: pymysql==0.9.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest + - ansible: stable-2.14 + db_engine_version: mariadb:10.4.27 + python: '3.9' + connector: mysqlclient==2.0.3 + docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.5.18 + # python: '3.9' + # connector: pymysql==0.9.3 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.5.18 + # python: '3.9' + # connector: mysqlclient==2.0.3 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest + + + # ================================================================== + # mariadb-client 10.6 + Python 3.10 + # ================================================================== + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: stable-2.13 + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: stable-2.14 + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + + # - ansible: devel + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: devel + # db_engine_version: mariadb:10.5.18 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + # - ansible: devel + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: pymysql==1.0.2 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest + # - ansible: devel + # db_engine_version: mariadb:10.6.11 + # python: '3.10' + # connector: mysqlclient==2.1.1 + # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + + services: + db_primary: + image: docker.io/library/${{ matrix.db_engine_version }} + env: + MARIADB_ROOT_PASSWORD: msandbox + MYSQL_ROOT_PASSWORD: msandbox + ports: + - 3307:3306 + # We write our own health-cmd because the mariadb container does not + # provide a healthcheck + options: >- + --health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1" + --health-start-period 10s + --health-interval 10s + --health-timeout 5s + --health-retries 6 + + db_replica1: + image: docker.io/library/${{ matrix.db_engine_version }} + env: + MARIADB_ROOT_PASSWORD: msandbox + MYSQL_ROOT_PASSWORD: msandbox + ports: + - 3308:3306 + options: >- + --health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1" + --health-start-period 10s + --health-interval 10s + --health-timeout 5s + --health-retries 6 + + db_replica2: + image: docker.io/library/${{ matrix.db_engine_version }} + env: + MARIADB_ROOT_PASSWORD: msandbox + MYSQL_ROOT_PASSWORD: msandbox + ports: + - 3309:3306 + options: >- + --health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1" + --health-start-period 10s + --health-interval 10s + --health-timeout 5s + --health-retries 6 + steps: + + # No need to check for service health. GitHub Action took care of it. + + - name: Restart MySQL server with settings for replication + run: | + docker exec ${{ job.services.db_primary.id }} bash -c 'echo -e [mysqld]\\nserver-id=1\\nlog-bin=/var/lib/mysql/primary-bin > /etc/mysql/conf.d/replication.cnf' + docker exec ${{ job.services.db_replica1.id }} bash -c 'echo -e [mysqld]\\nserver-id=2\\nlog-bin=/var/lib/mysql/replica1-bin > /etc/mysql/conf.d/replication.cnf' + docker exec ${{ job.services.db_replica2.id }} bash -c 'echo -e [mysqld]\\nserver-id=3\\nlog-bin=/var/lib/mysql/replica2-bin > /etc/mysql/conf.d/replication.cnf' + docker restart -t 30 ${{ job.services.db_primary.id }} + docker restart -t 30 ${{ job.services.db_replica1.id }} + docker restart -t 30 ${{ job.services.db_replica2.id }} + + - name: Wait for the primary to be healthy + run: | + while ! /usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" ${{ job.services.db_primary.id }} | grep healthy && [[ "$SECONDS" -lt 120 ]]; do sleep 1; done + - name: >- Perform integration testing against Ansible version ${{ matrix.ansible }} @@ -87,22 +354,17 @@ jobs: with: ansible-core-version: ${{ matrix.ansible }} pre-test-cmd: >- - DB_ENGINE=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $1}'); - DB_VERSION=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $2}'); - DB_ENGINE_PRETTY=$([[ "${DB_ENGINE}" == 'mysql' ]] && echo 'MySQL' || echo 'MariaDB'); - >&2 echo Matrix factor for the DB is ${{ matrix.db_engine_version }}...; - >&2 echo Setting ${DB_ENGINE_PRETTY} version to ${DB_VERSION}...; - sed -i -e "s/^${DB_ENGINE}_version:.*/${DB_ENGINE}_version: $DB_VERSION/g" '${{ env.mysql_version_file }}'; - if [[ ${{ matrix.db_engine_version }} == mariadb* ]]; - then - echo Set MariaDB install flag...; sed -i -e "s/^mariadb_install: false/mariadb_install: true/g" '${{ env.mysql_version_file }}'; - echo Set MariaDB v10.8.3 URL sub dir...; sed -i -e "s/^mariadb_url_subdir:.*/mariadb_url_subdir: linux-systemd/g" '${{ env.connector_version_file }}'; - fi; - >&2 echo Setting Connector version to ${{ matrix.connector }}...; - sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }} + echo Setting db_engine_version to "${{ matrix.db_engine_version }}"...; + echo -n "${{ matrix.db_engine_version }}" > tests/integration/db_engine_version; + echo Setting Connector version to "${{ matrix.connector }}"...; + echo -n "${{ matrix.connector }}" > tests/integration/connector; + echo Setting Python version to "${{ matrix.python }}"...; + echo -n "${{ matrix.python }}" > tests/integration/python; + echo Setting Ansible version to "${{ matrix.ansible }}"...; + echo -n "${{ matrix.ansible }}" > tests/integration/ansible + docker-image: ${{ matrix.docker_image }} target-python-version: ${{ matrix.python }} testing-type: integration - pull-request-change-detection: true units: runs-on: ubuntu-20.04 @@ -121,13 +383,13 @@ jobs: - 3.8 - 3.9 exclude: - - python: 3.8 + - python: '3.8' ansible: stable-2.13 - - python: 3.8 + - python: '3.8' ansible: stable-2.14 - - python: 3.8 + - python: '3.8' ansible: devel - - python: 3.9 + - python: '3.9' ansible: stable-2.12 steps: diff --git a/.github/workflows/ansible-test-roles.yml b/.github/workflows/ansible-test-roles.yml index 4748b5a..13e7d41 100644 --- a/.github/workflows/ansible-test-roles.yml +++ b/.github/workflows/ansible-test-roles.yml @@ -1,3 +1,4 @@ +--- name: Roles CI on: push: diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml new file mode 100644 index 0000000..fa10268 --- /dev/null +++ b/.github/workflows/build-docker-image.yml @@ -0,0 +1,67 @@ +--- +name: Build Docker Image for ansible-test + +on: + workflow_call: + inputs: + registry: + required: true + type: string + image_name: + required: true + type: string + context: + required: true + type: string + +jobs: + + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + # Requirement to use 'context' in docker/build-push-action@v3 + - name: Checkout repository + uses: actions/checkout@v3 + + # https://github.com/docker/login-action + - name: Log into registry ${{ inputs.registry }} + uses: docker/login-action@v2 + with: + registry: ${{ inputs.registry }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # https://github.com/docker/metadata-action + - name: Extract Docker metadata (tags, labels) + id: meta + uses: docker/metadata-action@v4 + with: + images: + "${{ inputs.registry }}\ + /${{ github.repository }}\ + /${{ inputs.image_name }}" + tags: latest + + # Setting up Docker Buildx with docker-container driver is required + # at the moment to be able to use a subdirectory with Git context + # + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + # https://github.com/docker/build-push-action + - name: Build and push Docker image with Buildx + id: build-and-push + uses: docker/build-push-action@v3 + with: + context: ${{ inputs.context }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml b/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml new file mode 100644 index 0000000..3d90270 --- /dev/null +++ b/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb103-py38-mysqlclient201 + +on: + push: + paths: + - 'test-containers/mariadb103-py38-mysqlclient201/**' + - '.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb103-py38-mysqlclient201 + context: test-containers/mariadb103-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml b/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml new file mode 100644 index 0000000..1ca4600 --- /dev/null +++ b/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb103-py38-pymysql093 + +on: + push: + paths: + - 'test-containers/mariadb103-py38-pymysql093/**' + - '.github/workflows/docker-image-mariadb103-py38-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb103-py38-pymysql093 + context: test-containers/mariadb103-py38-pymysql093 diff --git a/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml b/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml new file mode 100644 index 0000000..37e91ee --- /dev/null +++ b/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb103-py39-mysqlclient203 + +on: + push: + paths: + - 'test-containers/mariadb103-py39-mysqlclient203/**' + - '.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb103-py39-mysqlclient203 + context: test-containers/mariadb103-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml b/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml new file mode 100644 index 0000000..30acfc1 --- /dev/null +++ b/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb103-py39-pymysql093 + +on: + push: + paths: + - 'test-containers/mariadb103-py39-pymysql093/**' + - '.github/workflows/docker-image-mariadb103-py39-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb103-py39-pymysql093 + context: test-containers/mariadb103-py39-pymysql093 diff --git a/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml b/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml new file mode 100644 index 0000000..0fa7403 --- /dev/null +++ b/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb106-py310-mysqlclient211 + +on: + push: + paths: + - 'test-containers/mariadb106-py310-mysqlclient211/**' + - '.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb106-py310-mysqlclient211 + context: test-containers/mariadb106-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml b/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml new file mode 100644 index 0000000..adfe9e3 --- /dev/null +++ b/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb106-py310-pymysql102 + +on: + push: + paths: + - 'test-containers/mariadb106-py310-pymysql102/**' + - '.github/workflows/docker-image-mariadb106-py310-pymysql102.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb106-py310-pymysql102 + context: test-containers/mariadb106-py310-pymysql102 diff --git a/.github/workflows/docker-image-my57-py38-mysqlclient201.yml b/.github/workflows/docker-image-my57-py38-mysqlclient201.yml new file mode 100644 index 0000000..2c18f63 --- /dev/null +++ b/.github/workflows/docker-image-my57-py38-mysqlclient201.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my57-py38-mysqlclient201 + +on: + push: + paths: + - 'test-containers/my57-py38-mysqlclient201/**' + - '.github/workflows/docker-image-my57-py38-mysqlclient201.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my57-py38-mysqlclient201 + context: test-containers/my57-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-my57-py38-pymysql0711.yml b/.github/workflows/docker-image-my57-py38-pymysql0711.yml new file mode 100644 index 0000000..1568d22 --- /dev/null +++ b/.github/workflows/docker-image-my57-py38-pymysql0711.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my57-py38-pymysql0711 + +on: + push: + paths: + - 'test-containers/my57-py38-pymysql0711/**' + - '.github/workflows/docker-image-my57-py38-pymysql0711.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my57-py38-pymysql0711 + context: test-containers/my57-py38-pymysql0711 diff --git a/.github/workflows/docker-image-my57-py38-pymysql093.yml b/.github/workflows/docker-image-my57-py38-pymysql093.yml new file mode 100644 index 0000000..39bb583 --- /dev/null +++ b/.github/workflows/docker-image-my57-py38-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my57-py38-pymysql093 + +on: + push: + paths: + - 'test-containers/my57-py38-pymysql093/**' + - '.github/workflows/docker-image-my57-py38-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my57-py38-pymysql093 + context: test-containers/my57-py38-pymysql093 diff --git a/.github/workflows/docker-image-my80-py310-mysqlclient211.yml b/.github/workflows/docker-image-my80-py310-mysqlclient211.yml new file mode 100644 index 0000000..824f77c --- /dev/null +++ b/.github/workflows/docker-image-my80-py310-mysqlclient211.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py310-mysqlclient211 + +on: + push: + paths: + - 'test-containers/my80-py310-mysqlclient211/**' + - '.github/workflows/docker-image-my80-py310-mysqlclient211.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py310-mysqlclient211 + context: test-containers/my80-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-my80-py310-pymysql102.yml b/.github/workflows/docker-image-my80-py310-pymysql102.yml new file mode 100644 index 0000000..0c54e12 --- /dev/null +++ b/.github/workflows/docker-image-my80-py310-pymysql102.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py310-pymysql102 + +on: + push: + paths: + - 'test-containers/my80-py310-pymysql102/**' + - '.github/workflows/docker-image-my80-py310-pymysql102.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py310-pymysql102 + context: test-containers/my80-py310-pymysql102 diff --git a/.github/workflows/docker-image-my80-py38-mysqlclient201.yml b/.github/workflows/docker-image-my80-py38-mysqlclient201.yml new file mode 100644 index 0000000..0ac76b2 --- /dev/null +++ b/.github/workflows/docker-image-my80-py38-mysqlclient201.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py38-mysqlclient201 + +on: + push: + paths: + - 'test-containers/my80-py38-mysqlclient201/**' + - '.github/workflows/docker-image-my80-py38-mysqlclient201.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py38-mysqlclient201 + context: test-containers/my80-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-my80-py38-pymysql093.yml b/.github/workflows/docker-image-my80-py38-pymysql093.yml new file mode 100644 index 0000000..1677be6 --- /dev/null +++ b/.github/workflows/docker-image-my80-py38-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py38-pymysql093 + +on: + push: + paths: + - 'test-containers/my80-py38-pymysql093/**' + - '.github/workflows/docker-image-my80-py38-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py38-pymysql093 + context: test-containers/my80-py38-pymysql093 diff --git a/.github/workflows/docker-image-my80-py39-mysqlclient203.yml b/.github/workflows/docker-image-my80-py39-mysqlclient203.yml new file mode 100644 index 0000000..e6b41db --- /dev/null +++ b/.github/workflows/docker-image-my80-py39-mysqlclient203.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py39-mysqlclient203 + +on: + push: + paths: + - 'test-containers/my80-py39-mysqlclient203/**' + - '.github/workflows/docker-image-my80-py39-mysqlclient203.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py39-mysqlclient203 + context: test-containers/my80-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-my80-py39-pymysql093.yml b/.github/workflows/docker-image-my80-py39-pymysql093.yml new file mode 100644 index 0000000..72ffd60 --- /dev/null +++ b/.github/workflows/docker-image-my80-py39-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI my80-py39-pymysql093 + +on: + push: + paths: + - 'test-containers/my80-py39-pymysql093/*' + - '.github/workflows/docker-image-my80-py39-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-my80-py39-pymysql093 + context: test-containers/my80-py39-pymysql093 diff --git a/.gitignore b/.gitignore index 1922df0..9555f5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /tests/output/ +/tests/integration/inventory /changelogs/.plugin-cache.yaml *.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a94ffd8 --- /dev/null +++ b/Makefile @@ -0,0 +1,80 @@ +SHELL := /bin/bash + +# To tell ansible-test and Make to not kill the containers on failure or +# end of tests. Disabled by default. +ifdef keep_containers_alive + _keep_containers_alive = --docker-terminate never +endif + +# This match what GitHub Action will do. Disabled by default. +ifdef continue_on_errors + _continue_on_errors = --retry-on-error --continue-on-error +endif + +.PHONY: test-integration +test-integration: + echo -n $(db_engine_version) > tests/integration/db_engine_version + echo -n $(connector) > tests/integration/connector + echo -n $(python) > tests/integration/python + echo -n $(ansible) > tests/integration/ansible + # Create podman network for systems missing it. Error can be ignored + podman network create podman || true + podman run \ + --detach \ + --replace \ + --name primary \ + --env MARIADB_ROOT_PASSWORD=msandbox \ + --env MYSQL_ROOT_PASSWORD=msandbox \ + --network podman \ + --publish 3307:3306 \ + --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ + docker.io/library/$(db_engine_version) \ + mysqld + podman run \ + --detach \ + --replace \ + --name replica1 \ + --env MARIADB_ROOT_PASSWORD=msandbox \ + --env MYSQL_ROOT_PASSWORD=msandbox \ + --network podman \ + --publish 3308:3306 \ + --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ + docker.io/library/$(db_engine_version) \ + mysqld + podman run \ + --detach \ + --replace \ + --name replica2 \ + --env MARIADB_ROOT_PASSWORD=msandbox \ + --env MYSQL_ROOT_PASSWORD=msandbox \ + --network podman \ + --publish 3309:3306 \ + --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ + docker.io/library/$(db_engine_version) \ + mysqld + # Setup replication and restart containers + podman exec primary bash -c 'echo -e [mysqld]\\nserver-id=1\\nlog-bin=/var/lib/mysql/primary-bin > /etc/mysql/conf.d/replication.cnf' + podman exec replica1 bash -c 'echo -e [mysqld]\\nserver-id=2\\nlog-bin=/var/lib/mysql/replica1-bin > /etc/mysql/conf.d/replication.cnf' + podman exec replica2 bash -c 'echo -e [mysqld]\\nserver-id=3\\nlog-bin=/var/lib/mysql/replica2-bin > /etc/mysql/conf.d/replication.cnf' + # Don't restart a container unless it is healthy + while ! podman healthcheck run primary && [[ "$$SECONDS" -lt 120 ]]; do sleep 1; done + podman restart -t 30 primary + while ! podman healthcheck run replica1 && [[ "$$SECONDS" -lt 120 ]]; do sleep 1; done + podman restart -t 30 replica1 + while ! podman healthcheck run replica2 && [[ "$$SECONDS" -lt 120 ]]; do sleep 1; done + podman restart -t 30 replica2 + while ! podman healthcheck run primary && [[ "$$SECONDS" -lt 120 ]]; do sleep 1; done + mkdir -p .venv/$(ansible) + python$(local_python_version) -m venv .venv/$(ansible) + source .venv/$(ansible)/bin/activate + python$(local_python_version) -m ensurepip + python$(local_python_version) -m pip install --disable-pip-version-check https://github.com/ansible/ansible/archive/$(ansible).tar.gz + -set -x; ansible-test integration $(target) -v --color --coverage --diff --docker $(docker_image) --docker-network podman $(_continue_on_errors) $(_keep_containers_alive) --python $(python); set +x + rm tests/integration/db_engine_version + rm tests/integration/connector + rm tests/integration/python + rm tests/integration/ansible +ifndef keep_containers_alive + podman stop --time 0 --ignore primary replica1 replica2 + podman rm --ignore --volumes primary replica1 replica2 +endif diff --git a/README.md b/README.md index ac6eaea..09a88d8 100644 --- a/README.md +++ b/README.md @@ -62,23 +62,32 @@ Every voice is important and every idea is valuable. If you have something on yo ### ansible-core -- 2.11 - 2.12 - 2.13 +- 2.14 - current development version ### Databases -- mysql 5.7.31 -- mysql 8.0.22 -- mariadb 10.3.34 (only collection version >= 3) -- mariadb 10.8.3 (only collection version >= 3) +For MariaDB, only Long Term releases are tested. + +- mysql 5.7.40 +- mysql 8.0.31 +- mariadb:10.3.34 (only collection version <= 3.5.1) +- mariadb:10.4.24 (only collection version >= 3.5.2) +- mariadb:10.5.18 (only collection version >= 3.5.2) +- mariadb:10.6.11 (only collection version >= 3.5.2) +- mariadb:10.11.?? (waiting for release) + ### Database connectors -- pymysql 0.7.10 +- pymysql 0.7.11 (Only tested with MySQL 5.7) - pymysql 0.9.3 +- pymysql 1.0.2 (only collection version >= ???) !!! Unsuported until future release !!! - mysqlclient 2.0.1 +- mysqlclient 2.0.3 (only collection version >= 3.5.2) +- mysqlclient 2.1.1 (only collection version >= 3.5.2) ## External requirements diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 0000000..9aad0f5 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,87 @@ +# Tests + +This collection uses GitHub Actions to run ansible-test to validate its content. Three type of tests are used: Sanity, Integration and Units. + +The tests covers the code for plugins and roles (no role available yet, but tests are ready) and can be found here: + +- Plugins: *.github/workflows/ansible-test-plugins.yml* +- Roles: *.github/workflows/ansible-test-roles.yml* (unused yet) + +Everytime you push on your fork or you create a pull request, both workflows runs. You can see the output on the "Actions" tab. + + +## Integration tests + +You can use GitHub to run ansible-test either on the community repo or your fork. But sometimes you want to quickly test a single version or a single target. To do that, you can use the Makefile present at the root of this repository. + +For now, the makefile only supports Podman. + +### Requirements + +- python >= 3.8 and <= 3.10 +- make +- Minimum 15GB of free space on the device storing containers images and volumes. You can use this command to check: `podman system info --format='{{.Store.GraphRoot}}'|xargs findmnt --noheadings --nofsroot --output SOURCE --target|xargs df -h --output=size,used,avail,pcent,target` +- Minimum 2GB of RAM + + +### Makefile options + +The Makefile accept the following options: + +- **local_python_version**: This option can be omitted if your system has a version supported by Ansible. You can check with `python -V`. +- **ansible**: Mandatory version of ansible to install in a venv to run ansible-test. +- **docker_image**: + The container image to use to run our tests. Those images Dockerfile are in https://github.com/community.mysql/test-containers and then pushed to quay.io: E.G.: + `quay.io/mws/community-mysql-test-containers-my57-py38-mysqlclient201-pymysql0711:latest`. Look in the link above for a complete list of available containers. You can also look into `.github/workflows/ansible-test-plugins.yml` + Unfortunatly you must provide the right container_image yourself. And you still need to provides db_engine_version, python, etc... because ansible-test won't do black magic to try to detect what we expect. Explicit is better than implicit anyway. + To minimise the amount of images, pymysql 0.7.11 and mysqlclient are shipped together. +- **db_engine_version**: The name of the container to use for the service containers that will host a primary database and two replicas. Either MYSQL or MariaDB. Use ':' as a separator. Do not use short version, like mysql:8 for instance. Our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. +- **connector**: The name of the python package of the connector along with its version number. Use '==' as a separator. +- **python**: The python version to use in the controller. +- **target** : If omitted, all test targets will run. But you can limit the tests to a single target to speed up your tests. +- **keep_containers_alive**: This option keeps all tree databases containers and the ansible-test container alive at the end of tests or in case of failure. This is useful to enter one of the containers with `podman exec -it bash` for debugging. Rerunning the +test will recreate those containers. +- **continue_on_errors**: Tells ansible-test to retry on errors and also continue on errors. This is the way the GitHub Action's workflow runs the tests. If you develop a new target, this option can be used to validate that your tests cleanup everything so a new run can restart without errors like "Failed to create database x because it already exists". + +Examples: + +```sh +# Run all targets +make ansible="stable-2.12" db_engine_version="mysql:5.7.40" python="3.8" connector="pymysql==0.7.11" docker_image="ghcr.io/community.mysql/test-container-my57-py38-pymysql0711:latest" + +# A single target +make ansible="stable-2.14" db_engine_version="mysql:5.7.40" python="3.8" connector="pymysql==0.7.11" docker_image="ghcr.io/community.mysql/test-container-my57-py38-pymysql0711:latest" target="test_mysql_db" + +# Keep databases and ansible tests containers alives +# A single target and continue on errors +make ansible="stable-2.14" db_engine_version="mysql:8.0.31" python="3.9" connector="mysqlclient==2.0.3" docker_image="ghcr.io/community.mysql/test-container-my80-py39-mysqlclient203:latest" target="test_mysql_db" keep_containers_alive=1 continue_on_errors=1 + +# If your system has an usupported version of Python: +make local_python_version="3.8" ansible="stable-2.14" db_engine_version="mariadb:10.6.11" python="3.9" connector="pymysql==0.9.3" docker_image="ghcr.io/community.mysql/test-container-mariadb103-py39-pymysql093:latest" +``` + + +### Run all tests + +GitHub Action offer a test matrix that run every combination of Python, MySQL, MariaDB and Connector against each other. To reproduce this, this repo provides a script called *run_all_tests.py*. + +Examples: + +```sh +python run_all_tests.py +``` + + +### Add a new Python, Connector or Database version + +1. Add a workflow in [.github/workflows/](.github/workflows) +1. Add a new folder in [test-containers](test-containers) containing a new Dockerfile. Your container must contains 3 things: + - The python interpreter + - The python package to connect to the database (pymysql, mysqlclient, ...) + - A mysql client to query the database before to prepare tests before our tests starts. This client must provide both `mysql` and `mysqldump` commands. +1. Add your version in *.github/workflows/ansible-test-plugins.yml* + +After pushing the commit to the remote, the container will be build and published on ghcr.io. Have a look in the "Action" tab to see if it worked. In case of error `failed to copy: io: read/write on closed pipe` re-run the workflow, this append unfortunately a lot. + +To see the docker image produced, go to the main GitHub page of your fork or community.mysql (depending were you pushed) and look for the link "Packages" on the right hand side of the page. This page indicate a "Published x days ago" that is updated infrequently. To see the last time the container has been updated you must click on its title and look in the right hands side bellow the title "Last published". + diff --git a/changelogs/fragments/490_refactor_integration_tests.yml b/changelogs/fragments/490_refactor_integration_tests.yml new file mode 100644 index 0000000..0762adf --- /dev/null +++ b/changelogs/fragments/490_refactor_integration_tests.yml @@ -0,0 +1,6 @@ +--- +minor_changes: + - Integration tests - Add more versions of MariaDB + - Integration tests - Carefully verify every component of the tests in the new target 'setup_controller' to ensure expected versions are correct Python, Ansible, connector and MySQL/MariaDB. + - Integration tests - Add tools to test locally the same as on GHA by using same containers and virtualenv. Custom test containers are published in ghcr.io by this repo's workflows. MySQL/MariaDB are official Docker Hub images. + - Integration tests - New name for many tasks to makes it easier to find failing tests. Rename duplicates. Add name for tasks which doesn't had one, refactor some tests files to better group tests by subject, ... diff --git a/changelogs/fragments/backport-stable-1-pr-490.yml b/changelogs/fragments/backport-stable-1-pr-490.yml new file mode 100644 index 0000000..5aab754 --- /dev/null +++ b/changelogs/fragments/backport-stable-1-pr-490.yml @@ -0,0 +1,3 @@ +--- +trivial: + - Integration tests - Backport PR490 diff --git a/run_all_tests.py b/run_all_tests.py new file mode 100755 index 0000000..b7779a5 --- /dev/null +++ b/run_all_tests.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +import yaml +import os + +github_workflow_file = '.github/workflows/ansible-test-plugins.yml' + + +def read_github_workflow_file(): + with open(github_workflow_file, 'r') as gh_file: + try: + return yaml.safe_load(gh_file) + except yaml.YAMLError as exc: + print(exc) + + +def extract_value(target, dict_yaml): + for key, value in dict_yaml.items(): + if key == target: + return value + + +def extract_matrix(workflow_yaml): + jobs = extract_value('jobs', workflow_yaml) + integration = extract_value('integration', jobs) + strategy = extract_value('strategy', integration) + matrix = extract_value('matrix', strategy) + return matrix + + +# def is_exclude(exclude_list, test_suite): +# test_is_excluded = False +# for excl in exclude_list: +# match = 0 + +# if 'ansible' in excl: +# if excl.get('ansible') == test_suite[0]: +# match += 1 + +# if 'db_engine_version' in excl: +# if excl.get('db_engine_version') == test_suite[1]: +# match += 1 + +# if 'python' in excl: +# if excl.get('python') == test_suite[2]: +# match += 1 + +# if 'connector' in excl: +# if excl.get('connector') == test_suite[3]: +# match += 1 + +# if match > 1: +# test_is_excluded = True + +# return test_is_excluded + + +def main(): + workflow_yaml = read_github_workflow_file() + tests_matrix_yaml = extract_matrix(workflow_yaml) + + # matrix = [] + # exclude_list = tests_matrix_yaml.get('exclude') + # for ansible in tests_matrix_yaml.get('ansible'): + # for db_engine in tests_matrix_yaml.get('db_engine_version'): + # for python in tests_matrix_yaml.get('python'): + # for connector in tests_matrix_yaml.get('connector'): + # if not is_exclude(exclude_list, (ansible, db_engine, python, connector)): + # matrix.append((ansible, db_engine, python, connector)) + + for tests in tests_matrix_yaml.get('include'): + a = tests.get('ansible') + d = tests.get('db_engine_version') + p = tests.get('python') + c = tests.get('connector') + i = tests.get('docker_image') + make_cmd = f'make ansible="{a}" db_engine_version="{d}" python="{p}" connector="{c}" docker_image="{i}" test-integration' + print(f'Run tests for: Ansible: {a}, DB: {d}, Python: {p}, Connector: {c}, Docker image: {i}') + os.system(make_cmd) + # TODO, allow for CTRL+C to break the loop more easily + # TODO, store the failures from this iteration + # TODO, display a summary of failures from every iterations + + +if __name__ == '__main__': + main() diff --git a/test-containers/mariadb103-py38-mysqlclient201/Dockerfile b/test-containers/mariadb103-py38-mysqlclient201/Dockerfile new file mode 100644 index 0000000..68ea3f6 --- /dev/null +++ b/test-containers/mariadb103-py38-mysqlclient201/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mariadb-client-10.3 + +# iproute2 # To grab docker network gateway address +# python3.8-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + python3.8-dev \ + mariadb-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.0.1 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/mariadb103-py38-pymysql093/Dockerfile b/test-containers/mariadb103-py38-pymysql093/Dockerfile new file mode 100644 index 0000000..22c8c57 --- /dev/null +++ b/test-containers/mariadb103-py38-pymysql093/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mariadb-client-10.3 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + mariadb-client \ + iproute2 + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir pymysql==0.9.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/mariadb103-py39-mysqlclient203/Dockerfile b/test-containers/mariadb103-py39-mysqlclient203/Dockerfile new file mode 100644 index 0000000..b7837b2 --- /dev/null +++ b/test-containers/mariadb103-py39-mysqlclient203/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mariadb-client-10.3 + +# iproute2 # To grab docker network gateway address +# python3.9-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.9 \ + python3.9-dev \ + mariadb-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.9 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.0.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/mariadb103-py39-pymysql093/Dockerfile b/test-containers/mariadb103-py39-pymysql093/Dockerfile new file mode 100644 index 0000000..a1451ff --- /dev/null +++ b/test-containers/mariadb103-py39-pymysql093/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mariadb-client-10.3 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.9 \ + mariadb-client \ + iproute2 + +RUN python3.9 -m pip install --disable-pip-version-check --no-cache-dir pymysql==0.9.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/mariadb106-py310-mysqlclient211/Dockerfile b/test-containers/mariadb106-py310-mysqlclient211/Dockerfile new file mode 100644 index 0000000..f7e9eb1 --- /dev/null +++ b/test-containers/mariadb106-py310-mysqlclient211/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2204-test-container:main +# ubuntu2204 comes with mariadb-client-10.6 + +# iproute2 # To grab docker network gateway address +# python3.10-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.10 \ + python3.10-dev \ + mariadb-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.10 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.1.1 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/mariadb106-py310-pymysql102/Dockerfile b/test-containers/mariadb106-py310-pymysql102/Dockerfile new file mode 100644 index 0000000..afe6a77 --- /dev/null +++ b/test-containers/mariadb106-py310-pymysql102/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu2204-test-container:main +# ubuntu2204 comes with mariadb-client-10.6 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.10 \ + mariadb-client \ + iproute2 + +RUN python3.10 -m pip install --disable-pip-version-check --no-cache-dir pymysql==1.0.2 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my57-py38-mysqlclient201/Dockerfile b/test-containers/my57-py38-mysqlclient201/Dockerfile new file mode 100644 index 0000000..0eb1778 --- /dev/null +++ b/test-containers/my57-py38-mysqlclient201/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu1804-test-container:main +# ubuntu1804 comes with mysql-client-5.7 + +# iproute2 # To grab docker network gateway address +# python3.8-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + python3.8-dev \ + mysql-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.0.1 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my57-py38-pymysql0711/Dockerfile b/test-containers/my57-py38-pymysql0711/Dockerfile new file mode 100644 index 0000000..9141709 --- /dev/null +++ b/test-containers/my57-py38-pymysql0711/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu1804-test-container:main +# ubuntu1804 comes with mysql-client-5.7 + +# iproute2 # To grab docker network gateway address +# python3.8-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + python3.8-dev \ + mysql-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir pymysql==0.7.11 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my57-py38-pymysql093/Dockerfile b/test-containers/my57-py38-pymysql093/Dockerfile new file mode 100644 index 0000000..6b0f519 --- /dev/null +++ b/test-containers/my57-py38-pymysql093/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu1804-test-container:main +# ubuntu1804 comes with mysql-client-5.7 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + mysql-client \ + iproute2 + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir pymysql==0.9.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py310-mysqlclient211/Dockerfile b/test-containers/my80-py310-mysqlclient211/Dockerfile new file mode 100644 index 0000000..1aea0cd --- /dev/null +++ b/test-containers/my80-py310-mysqlclient211/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2204-test-container:main +# ubuntu2204 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +# python3.10-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.10 \ + python3.10-dev \ + mysql-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.10 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.1.1 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py310-pymysql102/Dockerfile b/test-containers/my80-py310-pymysql102/Dockerfile new file mode 100644 index 0000000..871a1e4 --- /dev/null +++ b/test-containers/my80-py310-pymysql102/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu2204-test-container:main +# ubuntu2204 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.10 \ + mysql-client \ + iproute2 + +RUN python3.10 -m pip install --disable-pip-version-check --no-cache-dir pymysql==1.0.2 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py38-mysqlclient201/Dockerfile b/test-containers/my80-py38-mysqlclient201/Dockerfile new file mode 100644 index 0000000..eb835c2 --- /dev/null +++ b/test-containers/my80-py38-mysqlclient201/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +# python3.8-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + python3.8-dev \ + mysql-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.0.1 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py38-pymysql093/Dockerfile b/test-containers/my80-py38-pymysql093/Dockerfile new file mode 100644 index 0000000..e97e5e2 --- /dev/null +++ b/test-containers/my80-py38-pymysql093/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.8 \ + mysql-client \ + iproute2 + +RUN python3.8 -m pip install --disable-pip-version-check --no-cache-dir pymysql==0.9.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py39-mysqlclient203/Dockerfile b/test-containers/my80-py39-mysqlclient203/Dockerfile new file mode 100644 index 0000000..396d895 --- /dev/null +++ b/test-containers/my80-py39-mysqlclient203/Dockerfile @@ -0,0 +1,21 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +# python3.9-dev # Reqs for mysqlclient +# default-libmysqlclient-dev # Reqs for mysqlclient +# build-essential # Reqs for mysqlclient +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.9 \ + python3.9-dev \ + mysql-client \ + iproute2 \ + default-libmysqlclient-dev \ + build-essential + +RUN python3.9 -m pip install --disable-pip-version-check --no-cache-dir mysqlclient==2.0.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/test-containers/my80-py39-pymysql093/Dockerfile b/test-containers/my80-py39-pymysql093/Dockerfile new file mode 100644 index 0000000..57ef15e --- /dev/null +++ b/test-containers/my80-py39-pymysql093/Dockerfile @@ -0,0 +1,16 @@ +FROM quay.io/ansible/ubuntu2004-test-container:main +# ubuntu2004 comes with mysql-client-8 + +# iproute2 # To grab docker network gateway address +RUN apt-get update -y && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + python3.9 \ + mysql-client \ + iproute2 + +# cffi # To connect to MySQL 8 with Python3.9 and PyMySQL +RUN python3.9 -m pip install --disable-pip-version-check --no-cache-dir cffi pymysql==0.9.3 + +ENV container=docker +CMD ["/sbin/init"] diff --git a/tests/integration/old_mariadb_replication/defaults/main.yml b/tests/integration/old_mariadb_replication/defaults/main.yml index 3751f4e..eb32dc1 100644 --- a/tests/integration/old_mariadb_replication/defaults/main.yml +++ b/tests/integration/old_mariadb_replication/defaults/main.yml @@ -1,3 +1,5 @@ +--- +mysql_host: "{{ gateway_addr }}" master_port: 3306 standby_port: 3307 test_db: test_db diff --git a/tests/integration/old_mariadb_replication/tasks/mariadb_master_use_gtid.yml b/tests/integration/old_mariadb_replication/tasks/mariadb_master_use_gtid.yml index e3e7605..699b61f 100644 --- a/tests/integration/old_mariadb_replication/tasks/mariadb_master_use_gtid.yml +++ b/tests/integration/old_mariadb_replication/tasks/mariadb_master_use_gtid.yml @@ -11,7 +11,7 @@ # Auxiliary step: - name: Get master status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: getmaster register: primary_status @@ -19,10 +19,10 @@ # Set master_use_gtid disabled: - name: Run replication mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: changemaster - master_host: 127.0.0.1 + master_host: '{{ mysql_host }}' master_port: "{{ primary_db.port }}" master_user: "{{ replication_user }}" master_password: "{{ replication_pass }}" @@ -38,13 +38,13 @@ # Start standby for further tests: - name: Start standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: startslave - name: Get standby status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: getslave register: slave_status @@ -56,7 +56,7 @@ # Stop standby for further tests: - name: Stop standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave @@ -67,7 +67,7 @@ # Auxiliary step: - name: Get master status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: getmaster register: primary_status @@ -75,10 +75,10 @@ # Set master_use_gtid current_pos: - name: Run replication mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: changemaster - master_host: 127.0.0.1 + master_host: '{{ mysql_host }}' master_port: "{{ primary_db.port }}" master_user: "{{ replication_user }}" master_password: "{{ replication_pass }}" @@ -94,13 +94,13 @@ # Start standby for further tests: - name: Start standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: startslave - name: Get standby status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: getslave register: slave_status @@ -112,7 +112,7 @@ # Stop standby for further tests: - name: Stop standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave @@ -123,7 +123,7 @@ # Auxiliary step: - name: Get master status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: getmaster register: primary_status @@ -131,10 +131,10 @@ # Set master_use_gtid slave_pos: - name: Run replication mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: changemaster - master_host: 127.0.0.1 + master_host: '{{ mysql_host }}' master_port: "{{ primary_db.port }}" master_user: "{{ replication_user }}" master_password: "{{ replication_pass }}" @@ -150,13 +150,13 @@ # Start standby for further tests: - name: Start standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: startslave - name: Get standby status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: getslave register: slave_status @@ -168,6 +168,6 @@ # Stop standby for further tests: - name: Stop standby mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave diff --git a/tests/integration/old_mariadb_replication/tasks/mariadb_replication_connection_name.yml b/tests/integration/old_mariadb_replication/tasks/mariadb_replication_connection_name.yml index 98fa5fe..3928c78 100644 --- a/tests/integration/old_mariadb_replication/tasks/mariadb_replication_connection_name.yml +++ b/tests/integration/old_mariadb_replication/tasks/mariadb_replication_connection_name.yml @@ -4,20 +4,20 @@ # Needs for further tests: - name: Stop slave mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave - name: Reset slave all mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: resetslaveall # Get master log pos: - name: Get master status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: getmaster register: primary_status @@ -25,10 +25,10 @@ # Test changemaster mode: - name: Run replication with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: changemaster - master_host: 127.0.0.1 + master_host: '{{ mysql_host }}' master_port: "{{ primary_db.port }}" master_user: "{{ replication_user }}" master_password: "{{ replication_pass }}" @@ -45,7 +45,7 @@ # Test startslave mode: - name: Start slave with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: startslave connection_name: "{{ conn_name }}" @@ -59,7 +59,7 @@ # Test getslave mode: - name: Get standby statu with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: getslave connection_name: "{{ conn_name }}" @@ -68,7 +68,7 @@ - assert: that: - slave_status.Is_Slave == true - - slave_status.Master_Host == '127.0.0.1' + - slave_status.Master_Host == ''{{ mysql_host }}'' - slave_status.Exec_Master_Log_Pos == primary_status.Position - slave_status.Master_Port == {{ primary_db.port }} - slave_status.Last_IO_Errno == 0 @@ -78,7 +78,7 @@ # Test stopslave mode: - name: Stop slave with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave connection_name: "{{ conn_name }}" @@ -92,7 +92,7 @@ # Test reset - name: Reset slave with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: resetslave connection_name: "{{ conn_name }}" @@ -106,7 +106,7 @@ # Test reset all - name: Reset slave all with connection_name mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: resetslaveall connection_name: "{{ conn_name }}" diff --git a/tests/integration/old_mariadb_replication/tasks/mariadb_replication_initial.yml b/tests/integration/old_mariadb_replication/tasks/mariadb_replication_initial.yml index 86a6760..f65d090 100644 --- a/tests/integration/old_mariadb_replication/tasks/mariadb_replication_initial.yml +++ b/tests/integration/old_mariadb_replication/tasks/mariadb_replication_initial.yml @@ -3,11 +3,11 @@ # Preparation: - name: Create user for replication - shell: "echo \"GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; FLUSH PRIVILEGES;\" | mysql -P {{ primary_db.port }} -h 127.0.0.1" + shell: "echo \"GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; FLUSH PRIVILEGES;\" | mysql -P {{ primary_db.port }} -h '{{ mysql_host }}'" - name: Create test database mysql_db: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ primary_db.port }}' state: present name: '{{ test_db }}' @@ -16,12 +16,12 @@ shell: 'mysqldump -P {{ primary_db.port }} -h 127.0.01 --all-databases --master-data=2 > {{ dump_path }}' - name: Restore the dump to the replica - shell: 'mysql -P {{ replica_db.port }} -h 127.0.0.1 < {{ dump_path }}' + shell: "mysql -P {{ replica_db.port }} -h '{{ mysql_host }}' < {{ dump_path }}" # Test getmaster mode: - name: Get master status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ primary_db.port }}" mode: getmaster register: master_status @@ -35,10 +35,10 @@ # Test changemaster mode: - name: Run replication mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: changemaster - master_host: 127.0.0.1 + master_host: '{{ mysql_host }}' master_port: "{{ primary_db.port }}" master_user: "{{ replication_user }}" master_password: "{{ replication_pass }}" @@ -54,7 +54,7 @@ # Test startslave mode: - name: Start slave mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: startslave register: result @@ -67,7 +67,7 @@ # Test getslave mode: - name: Get replica status mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: getslave register: slave_status @@ -75,7 +75,7 @@ - assert: that: - slave_status.Is_Slave == true - - slave_status.Master_Host == '127.0.0.1' + - slave_status.Master_Host == ''{{ mysql_host }}'' - slave_status.Exec_Master_Log_Pos == master_status.Position - slave_status.Master_Port == {{ primary_db.port }} - slave_status.Last_IO_Errno == 0 @@ -85,7 +85,7 @@ # Test stopslave mode: - name: Stop slave mysql_replication: - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: "{{ replica_db.port }}" mode: stopslave register: result diff --git a/tests/integration/targets/setup_controller/tasks/fake_root.yml b/tests/integration/targets/setup_controller/tasks/fake_root.yml new file mode 100644 index 0000000..49531b8 --- /dev/null +++ b/tests/integration/targets/setup_controller/tasks/fake_root.yml @@ -0,0 +1,11 @@ +--- + +- name: "{{ role_name }} | Fake root | Ensure folder" + ansible.builtin.file: + path: "{{ playbook_dir }}/root" + state: directory + +- name: "{{ role_name }} | Fake root | Ensure default file exists" + ansible.builtin.file: + path: "{{ playbook_dir }}/root/.my.cnf" + state: touch diff --git a/tests/integration/targets/setup_controller/tasks/main.yml b/tests/integration/targets/setup_controller/tasks/main.yml new file mode 100644 index 0000000..0d5e36b --- /dev/null +++ b/tests/integration/targets/setup_controller/tasks/main.yml @@ -0,0 +1,18 @@ +--- +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +- name: Prepare the fake root folder + ansible.builtin.import_tasks: + file: fake_root.yml + +# setvars.yml requires the iproute2 package installed by install.yml +- name: Set variables + ansible.builtin.import_tasks: + file: setvars.yml + +- name: Verify all components version under test + ansible.builtin.import_tasks: + file: verify.yml diff --git a/tests/integration/targets/setup_controller/tasks/setvars.yml b/tests/integration/targets/setup_controller/tasks/setvars.yml new file mode 100644 index 0000000..d74136d --- /dev/null +++ b/tests/integration/targets/setup_controller/tasks/setvars.yml @@ -0,0 +1,69 @@ +--- + +- name: "{{ role_name }} | Setvars | Extract Podman/Docker Network Gateway" + ansible.builtin.shell: + cmd: ip route|grep default|awk '{print $3}' + register: ip_route_output + +- name: "{{ role_name }} | Setvars | Set Fact" + ansible.builtin.set_fact: + gateway_addr: "{{ ip_route_output.stdout }}" + connector_name_version: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/connector' + ) }} + db_engine_version: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/db_engine_version' + ) }} + python_version_lookup: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/python' + ) }} + ansible_version_lookup: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/ansible' + ) }} + +- name: "{{ role_name }} | Setvars | Set Fact using above facts" + ansible.builtin.set_fact: + connector_name: "{{ connector_name_version.split('=')[0].strip() }}" + connector_version: "{{ connector_name_version.split('=')[2].strip() }}" + db_engine: "{{ db_engine_version.split(':')[0].strip() }}" + db_version: "{{ db_engine_version.split(':')[1].strip() }}" + python_version: "{{ python_version_lookup.strip() }}" + test_ansible_version: >- + {%- if ansible_version_lookup == 'devel' -%} + {{ ansible_version_lookup }} + {%- else -%} + {{ ansible_version_lookup.split('-')[1].strip() }} + {%- endif -%} + mysql_command: >- + mysql + -h{{ gateway_addr }} + -P{{ mysql_primary_port }} + -u{{ mysql_user }} + -p{{ mysql_password }} + --protocol=tcp + mysql_command_wo_port: >- + mysql + -h{{ gateway_addr }} + -u{{ mysql_user }} + -p{{ mysql_password }} + --protocol=tcp + +- name: "{{ role_name }} | Setvars | Output test informations" + vars: + msg: |- + connector_name: {{ connector_name }} + connector_version: {{ connector_version }} + db_engine: {{ db_engine }} + db_version: {{ db_version }} + python_version: {{ python_version }} + test_ansible_version: {{ test_ansible_version }} + ansible.builtin.debug: + msg: "{{ msg.split('\n') }}" diff --git a/tests/integration/targets/setup_controller/tasks/verify.yml b/tests/integration/targets/setup_controller/tasks/verify.yml new file mode 100644 index 0000000..74aa0f2 --- /dev/null +++ b/tests/integration/targets/setup_controller/tasks/verify.yml @@ -0,0 +1,59 @@ +--- + +- vars: + mysql_parameters: &mysql_params + login_user: root + login_password: msandbox + login_host: "{{ gateway_addr }}" + login_port: 3307 + + block: + + - name: Query Primary container over TCP for MySQL/MariaDB version + mysql_info: + <<: *mysql_params + filter: + - version + register: primary_info + + - name: Assert that test container runs the expected MySQL/MariaDB version + assert: + that: + - "'{{ primary_info.version.major }}.{{ primary_info.version.minor }}\ + .{{ primary_info.version.release }}' == '{{ db_version }}'" + + - name: Assert that mysql_info module used the expected version of pymysql + assert: + that: + - primary_info.connector_name == connector_name + - primary_info.connector_version == connector_version + when: + - connector_name == 'pymysql' + + - name: Assert that mysql_info module used the expected version of mysqlclient + assert: + that: + - primary_info.connector_name == 'MySQLdb' + - primary_info.connector_version == connector_version + when: + - connector_name == 'mysqlclient' + + - name: Display the python version in use + command: + cmd: python{{ python_version }} -V + changed_when: false + register: python_in_use + + - name: Assert that expected Python is installed + assert: + that: + - python_in_use.stdout is search(python_version) + + - name: Assert that we run the expected ansible version + assert: + that: + - > + "{{ ansible_version.major }}.{{ ansible_version.minor }}" + is version(test_ansible_version, '==') + when: + - test_ansible_version != 'devel' # Devel will change overtime diff --git a/tests/integration/targets/setup_mysql/defaults/main.yml b/tests/integration/targets/setup_mysql/defaults/main.yml deleted file mode 100644 index cceb8f5..0000000 --- a/tests/integration/targets/setup_mysql/defaults/main.yml +++ /dev/null @@ -1,18 +0,0 @@ -dbdeployer_version: 1.64.0 -dbdeployer_home_dir: /opt/dbdeployer - -home_dir: /root - -mariadb_install: false - -mysql_version: 8.0.22 -mariadb_version: 10.5.4 - -mysql_base_port: 3306 - -percona_client_package: >- - {%- if mariadb_install -%} - mariadb-client - {%- else -%} - percona-server-client-5.7 - {%- endif -%} diff --git a/tests/integration/targets/setup_mysql/handlers/main.yml b/tests/integration/targets/setup_mysql/handlers/main.yml deleted file mode 100644 index 090a5e7..0000000 --- a/tests/integration/targets/setup_mysql/handlers/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: "{{ role_name }} | handler | create dbdeployer installed file" - template: - src: installed_file.j2 - dest: "{{ dbdeployer_installed_file }}" - listen: create zookeeper installed file diff --git a/tests/integration/targets/setup_mysql/tasks/config.yml b/tests/integration/targets/setup_mysql/tasks/config.yml deleted file mode 100644 index 2b27e27..0000000 --- a/tests/integration/targets/setup_mysql/tasks/config.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -- name: "{{ role_name }} | config | download mysql tarball" - get_url: - url: "{{ install_src }}" - dest: "{{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }}" - -- name: "{{ role_name }} | config | run unpack tarball" - shell: - cmd: "dbdeployer unpack {{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }} --flavor {{ install_type }}" - creates: "{{ dbdeployer_sandbox_binary_dir }}/{{ install_version }}" - -- name: "{{ role_name }} | config | setup replication topology" - shell: - cmd: "dbdeployer deploy multiple {{ install_version }} --flavor {{ install_type }} --base-port {{ mysql_base_port }} --my-cnf-options=\"master_info_repository='TABLE'\" --my-cnf-options=\"relay_log_info_repository='TABLE'\"" - creates: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}" diff --git a/tests/integration/targets/setup_mysql/tasks/dir.yml b/tests/integration/targets/setup_mysql/tasks/dir.yml deleted file mode 100644 index dc02879..0000000 --- a/tests/integration/targets/setup_mysql/tasks/dir.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: "{{ role_name }} | dir | create dbdeployer directories" - file: - state: directory - path: "{{ item }}" - loop: - - "{{ dbdeployer_home_dir }}" - - "{{ dbdeployer_install_dir }}" - - "{{ dbdeployer_sandbox_download_dir }}" - - "{{ dbdeployer_sandbox_binary_dir }}" - - "{{ dbdeployer_sandbox_home_dir }}" diff --git a/tests/integration/targets/setup_mysql/tasks/install.yml b/tests/integration/targets/setup_mysql/tasks/install.yml deleted file mode 100644 index b64af25..0000000 --- a/tests/integration/targets/setup_mysql/tasks/install.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -- name: "{{ role_name }} | install | add apt signing key for percona" - apt_key: - keyserver: keyserver.ubuntu.com - id: 4D1BB29D63D98E422B2113B19334A25F8507EFA5 - state: present - when: install_type == 'mysql' - -- name: "{{ role_name }} | install | add percona repositories" - apt_repository: - repo: deb http://repo.percona.com/percona/apt {{ ansible_lsb.codename }} main - state: present - when: install_type == 'mysql' - -- name: "{{ role_name }} | install | add apt signing key for mariadb" - apt_key: - keyserver: keyserver.ubuntu.com - id: F1656F24C74CD1D8 - state: present - when: install_type == 'mariadb' - -- name: "{{ role_name }} | install | add mariadb repositories" - apt_repository: - repo: "deb [arch=amd64,arm64] https://downloads.mariadb.com/MariaDB/mariadb-{{ mysql_major_version }}/repo/ubuntu {{ ansible_lsb.codename }} main" - state: present - when: install_type == 'mariadb' - -- name: "{{ role_name }} | install | install packages required by percona" - apt: - name: "{{ percona_mysql_packages }}" - state: present - environment: - DEBIAN_FRONTEND: noninteractive - -- name: "{{ role_name }} | install | install packages required by mysql connector" - apt: - name: "{{ install_python_prereqs }}" - state: present - environment: - DEBIAN_FRONTEND: noninteractive - -- name: "{{ role_name }} | install | install python packages" - pip: - name: "{{ python_packages }}" - register: connector - -- name: Extract connector.name.0 content - set_fact: - connector_name: "{{ connector.name.0 }}" - -- name: Debug connector_name content - debug: - msg: '{{ connector_name }}' - -- name: Extract connector version - set_fact: - connector_ver: "{{ connector_name.split('=')[2].strip() }}" - -- name: Debug connector_ver var content - debug: - msg: '{{ connector_ver }}' - -- name: "{{ role_name }} | install | install packages required by mysql" - apt: - name: "{{ install_prereqs }}" - state: present - environment: - DEBIAN_FRONTEND: noninteractive - -- name: "{{ role_name }} | install | download and unpack dbdeployer" - unarchive: - remote_src: true - src: "{{ dbdeployer_src }}" - dest: "{{ dbdeployer_install_dir }}" - creates: "{{ dbdeployer_installed_file }}" - register: dbdeployer_tarball_install - notify: - - create zookeeper installed file - until: dbdeployer_tarball_install is not failed - retries: 6 - delay: 5 - -- name: "{{ role_name }} | install | create symlink" - file: - src: "{{ dbdeployer_install_dir }}/dbdeployer-{{ dbdeployer_version }}.linux" - dest: /usr/local/bin/dbdeployer - follow: false - state: link - -- meta: flush_handlers diff --git a/tests/integration/targets/setup_mysql/tasks/main.yml b/tests/integration/targets/setup_mysql/tasks/main.yml deleted file mode 100644 index c6a8348..0000000 --- a/tests/integration/targets/setup_mysql/tasks/main.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -#################################################################### -# WARNING: These are designed specifically for Ansible tests # -# and should not be used as examples of how to write Ansible roles # -#################################################################### - -- import_tasks: setvars.yml -- import_tasks: dir.yml -- import_tasks: install.yml -- import_tasks: config.yml -- import_tasks: verify.yml diff --git a/tests/integration/targets/setup_mysql/tasks/setvars.yml b/tests/integration/targets/setup_mysql/tasks/setvars.yml deleted file mode 100644 index cfc90c1..0000000 --- a/tests/integration/targets/setup_mysql/tasks/setvars.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -- name: "{{ role_name }} | setvars | split mysql version in parts" - set_fact: - mysql_version_parts: >- - {%- if mariadb_install -%} - {{ mariadb_version.split('.') }} - {%- else -%} - {{ mysql_version.split('.') }} - {%- endif -%} - -- name: "{{ role_name }} | setvars | get mysql major version" - set_fact: - mysql_major_version: "{{ mysql_version_parts[0] + '.' + mysql_version_parts[1] }}" - -- name: "{{ role_name }} | setvars | set the appropriate extension dependent on the mysql version" - set_fact: - mysql_compression_extension: "{{ mysql_version is version('8.0.0', '<') | ternary('gz', 'xz') }}" - -- name: "{{ role_name }} | setvars | set the install type" - set_fact: - install_type: "{{ mariadb_install | ternary('mariadb', 'mysql') }}" - -- name: "{{ role_name }} | setvars | set install_version" - set_fact: - install_version: "{{ lookup('vars', install_type + '_version') }}" - -- name: "{{ role_name }} | setvars | set install_tarball" - set_fact: - install_tarball: "{{ lookup('vars', install_type + '_tarball') }}" - -- name: "{{ role_name }} | setvars | set install_src" - set_fact: - install_src: "{{ lookup('vars', install_type + '_src') }}" diff --git a/tests/integration/targets/setup_mysql/tasks/verify.yml b/tests/integration/targets/setup_mysql/tasks/verify.yml deleted file mode 100644 index ca383d9..0000000 --- a/tests/integration/targets/setup_mysql/tasks/verify.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- name: "{{ role_name }} | verify | confirm primary is running and get the port" - shell: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}/n1 -BNe'select @@port'" - register: primary_port - -- name: "{{ role_name }} | verify | confirm replica1 is running and get the port" - shell: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}/n2 -BNe'select @@port'" - register: replica1_port - -- name: "{{ role_name }} | verify | confirm replica2 is running and get the port" - shell: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}/n3 -BNe'select @@port'" - register: replica2_port - -- name: "{{ role_name }} | verify | confirm primary is running on expected port" - assert: - that: - - primary_port.stdout|int == 3307 - -- name: "{{ role_name }} | verify | confirm replica1 is running on expected port" - assert: - that: - - replica1_port.stdout|int == 3308 - -- name: "{{ role_name }} | verify | confirm replica2 is running on expected port" - assert: - that: - - replica2_port.stdout|int == 3309 diff --git a/tests/integration/targets/setup_mysql/templates/installed_file.j2 b/tests/integration/targets/setup_mysql/templates/installed_file.j2 deleted file mode 100644 index 862a357..0000000 --- a/tests/integration/targets/setup_mysql/templates/installed_file.j2 +++ /dev/null @@ -1 +0,0 @@ -{{ dbdeployer_version }} diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml deleted file mode 100644 index 8fbcd90..0000000 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -dbdeployer_install_dir: "{{ dbdeployer_home_dir }}/dbdeployer_{{ dbdeployer_version }}" -dbdeployer_src: "https://github.com/datacharmer/dbdeployer/releases/download/v{{ dbdeployer_version }}/dbdeployer-{{ dbdeployer_version }}.linux.tar.gz" -dbdeployer_installed_file: "{{ dbdeployer_home_dir }}/dbdeployer_installed" - -dbdeployer_sandbox_download_dir: "{{ home_dir }}/downloads" -dbdeployer_sandbox_binary_dir: "{{ home_dir }}/opt/mysql" -dbdeployer_sandbox_home_dir: "{{ home_dir }}/sandboxes" - -percona_mysql_packages: - - "{{ percona_client_package }}" - -python_packages: [pymysql == 0.9.3] - -install_prereqs: - - libaio1 - - libnuma1 - - libncurses5 - -install_python_prereqs: - - python3-dev - - python3-cryptography - - default-libmysqlclient-dev - - build-essential - -mysql_tarball: "mysql-{{ mysql_version }}-linux-glibc2.12-x86_64.tar.{{ mysql_compression_extension }}" -mysql_src: "https://cdn.mysql.com/archives/mysql-{{ mysql_major_version }}/{{ mysql_tarball }}" -mariadb_url_subdir: "linux" -mariadb_tarball: "mariadb-{{ mariadb_version }}-{{ mariadb_url_subdir }}-x86_64.tar.gz" -mariadb_src: "https://downloads.mariadb.com/MariaDB/mariadb-{{ mariadb_version }}/bintar-{{ mariadb_url_subdir }}-x86_64/{{ mariadb_tarball }}" diff --git a/tests/integration/targets/test_mysql_db/defaults/main.yml b/tests/integration/targets/test_mysql_db/defaults/main.yml index 1c1577b..fb523dd 100644 --- a/tests/integration/targets/test_mysql_db/defaults/main.yml +++ b/tests/integration/targets/test_mysql_db/defaults/main.yml @@ -2,6 +2,7 @@ # defaults file for test_mysql_db mysql_user: root mysql_password: msandbox +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 # Database names diff --git a/tests/integration/targets/test_mysql_db/meta/main.yml b/tests/integration/targets/test_mysql_db/meta/main.yml index f1174ff..aebda43 100644 --- a/tests/integration/targets/test_mysql_db/meta/main.yml +++ b/tests/integration/targets/test_mysql_db/meta/main.yml @@ -1,2 +1,2 @@ dependencies: - - setup_mysql + - setup_controller diff --git a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml index c2fda2a..390c6ae 100644 --- a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml +++ b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml @@ -1,57 +1,59 @@ -- set_fact: +--- +- name: Config overrides | Set facts + set_fact: db_to_create: testdb1 - config_file: "/root/.my1.cnf" + config_file: "{{ playbook_dir }}/.my1.cnf" fake_port: 9999 fake_host: "blahblah.local" - include_dir: "/root/mycnf.d" + include_dir: "{{ playbook_dir }}/mycnf.d" -- name: Create custom config file +- name: Config overrides | Create custom config file shell: 'echo "[client]" > {{ config_file }}' -- name: Add fake port to config file +- name: Config overrides | Add fake port to config file shell: 'echo "port = {{ fake_port }}" >> {{ config_file }}' -- name: Add blank line +- name: Config overrides | Add blank line shell: 'echo "" >> {{ config_file }}' when: - > - connector_name is not search('pymysql') + connector_name != 'pymysql' or ( - connector_name is search('pymysql') - and connector_ver is version('0.9.3', '>=') + connector_name == 'pymysql' + and connector_version is version('0.9.3', '>=') ) -- name: Create include_dir +- name: Config overrides | Create include_dir file: path: '{{ include_dir }}' state: directory mode: '0777' when: - > - connector_name is not search('pymysql') + connector_name != 'pymysql' or ( - connector_name is search('pymysql') - and connector_ver is version('0.9.3', '>=') + connector_name == 'pymysql' + and connector_version is version('0.9.3', '>=') ) -- name: Add include_dir +- name: Config overrides | Add include_dir lineinfile: path: '{{ config_file }}' line: '!includedir {{ include_dir }}' insertafter: EOF when: - > - connector_name is not search('pymysql') + connector_name != 'pymysql' or ( - connector_name is search('pymysql') - and connector_ver is version('0.9.3', '>=') + connector_name == 'pymysql' + and connector_version is version('0.9.3', '>=') ) -- name: Create database using fake port to connect to, must fail +- name: Config overrides | Create database using fake port to connect to, must fail mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_to_create }}' state: present @@ -61,17 +63,17 @@ ignore_errors: yes register: result -- name: Must fail because login_port default has beed overriden by wrong value from config file +- name: Config overrides | Must fail because login_port default has beed overriden by wrong value from config file assert: that: - - result is failed - - result.msg is search("unable to connect to database") + - result is failed + - result.msg is search("unable to connect to database") -- name: Create database using default port +- name: Config overrides | Create database using default port mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_to_create }}' state: present @@ -80,22 +82,22 @@ config_overrides_defaults: no register: result -- name: Must not fail because of the default of login_port is correct +- name: Config overrides | Must not fail because of the default of login_port is correct assert: that: - - result is changed + - result is changed -- name: Reinit custom config file +- name: Config overrides | Reinit custom config file shell: 'echo "[client]" > {{ config_file }}' -- name: Add fake host to config file +- name: Config overrides | Add fake host to config file shell: 'echo "host = {{ fake_host }}" >> {{ config_file }}' -- name: Remove database using fake login_host +- name: Config overrides | Remove database using fake login_host mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_to_create }}' state: absent @@ -104,18 +106,17 @@ register: result ignore_errors: yes -- name: Must fail because login_host default has beed overriden by wrong value from config file +- name: Config overrides | Must fail because login_host default has beed overriden by wrong value from config file assert: that: - - result is failed - - result.msg is search("Can't connect to MySQL server on '{{ fake_host }}'") or result.msg is search("Unknown MySQL server host '{{ fake_host }}'") + - result is failed + - result.msg is search("Can't connect to MySQL server on '{{ fake_host }}'") or result.msg is search("Unknown MySQL server host '{{ fake_host }}'") -# Clean up -- name: Remove test db +- name: Config overrides | Clean up test database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_to_create }}' state: absent diff --git a/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml b/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml index 9ef3af5..02e5df2 100644 --- a/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml +++ b/tests/integration/targets/test_mysql_db/tasks/encoding_dump_import.yml @@ -1,45 +1,46 @@ --- -- set_fact: - latin1_file1: "{{tmp_dir}}/{{file}}" +- name: Encoding | Set fact + set_fact: + latin1_file1: "{{ tmp_dir }}/{{ file }}" - name: Deleting Latin1 encoded Database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_latin1_name }}' state: absent -- name: create Latin1 encoded database +- name: Encoding | Create Latin1 encoded database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_latin1_name }}' state: present encoding: latin1 -- name: create a table in Latin1 database +- name: Encoding | Create a table in Latin1 database command: "{{ mysql_command }} {{ db_latin1_name }} -e \"create table testlatin1(id int, name varchar(100))\"" # Inserting a string in latin1 into table, , this string be tested later, # so report any change of content in the test too -- name: inserting data into Latin1 database +- name: Encoding | Inserting data into Latin1 database command: "{{ mysql_command }} {{ db_latin1_name }} -e \"insert into testlatin1 value(47,'Amédée Bôlüt')\"" -- name: selecting table +- name: Encoding | Selecting table command: "{{ mysql_command }} {{ db_latin1_name }} -e \"select * from testlatin1\"" register: output -- name: Dumping a table in Latin1 database +- name: Encoding | Dumping a table in Latin1 database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: "{{ db_latin1_name }}" encoding: latin1 @@ -49,30 +50,30 @@ - assert: that: - - result is changed + - result is changed -- name: state dump - file name should exist +- name: Encoding | State dump - file name should exist (latin1_file1) file: name: '{{ latin1_file1 }}' state: file -- name: od the file and check of latin1 encoded string is present +- name: od the file and check of latin1 encoded string is present shell: grep -a 47 {{ latin1_file1 }} | od -c |grep "A m 351 d 351 e B 364\|A m 303 251 d 303 251 e B 303" -- name: Dropping {{ db_latin1_name }} database +- name: Encoding | Dropping {{ db_latin1_name }} database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_latin1_name }}' state: absent -- name: Importing the latin1 mysql script +- name: Encoding | Importing the latin1 mysql script mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' state: import encoding: latin1 @@ -80,20 +81,25 @@ target: "{{ latin1_file1 }}" register: result -- assert: +- name: Encoding | Assert that importing latin1 is changed + assert: that: - - result is changed + - result is changed -- name: check encoding of table - shell: "{{ mysql_command }} {{ db_latin1_name }} -e \"SHOW FULL COLUMNS FROM testlatin1\"" +- name: Encoding | Check encoding of table + ansible.builtin.command: + cmd: > + {{ mysql_command }} + {{ db_latin1_name }} + -e "SHOW FULL COLUMNS FROM {{ db_latin1_name }}.testlatin1" register: output failed_when: '"latin1_swedish_ci" not in output.stdout' -- name: remove database +- name: Encoding | Clean up database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_latin1_name }}' state: absent diff --git a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml index 54ff5a7..8ca0dc7 100644 --- a/tests/integration/targets/test_mysql_db/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_db/tasks/issue-28.yml @@ -9,7 +9,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: @@ -26,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -33,6 +34,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' tls_requires: @@ -44,7 +46,7 @@ state: absent login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem register: result @@ -53,12 +55,14 @@ - assert: that: - result is failed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' - assert: that: - result is succeeded - when: connector_name is not search('pymysql') + when: + - connector_name != 'pymysql' - name: attempt connection with newly created user ignoring hostname mysql_db: @@ -66,7 +70,7 @@ state: absent login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem check_hostname: no @@ -81,5 +85,5 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' - host: 127.0.0.1 + host_all: true state: absent diff --git a/tests/integration/targets/test_mysql_db/tasks/issue_256_mysqldump_errors.yml b/tests/integration/targets/test_mysql_db/tasks/issue_256_mysqldump_errors.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/targets/test_mysql_db/tasks/main.yml b/tests/integration/targets/test_mysql_db/tasks/main.yml index 958e341..42fb596 100644 --- a/tests/integration/targets/test_mysql_db/tasks/main.yml +++ b/tests/integration/targets/test_mysql_db/tasks/main.yml @@ -1,3 +1,4 @@ +--- #################################################################### # WARNING: These are designed specifically for Ansible tests # # and should not be used as examples of how to write Ansible roles # @@ -21,10 +22,6 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - - name: Check state present/absent include_tasks: state_present_absent.yml vars: diff --git a/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml b/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml index c2eb13c..0bd7d58 100644 --- a/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml +++ b/tests/integration/targets/test_mysql_db/tasks/multi_db_create_delete.yml @@ -18,7 +18,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -43,7 +43,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -75,7 +75,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -107,7 +107,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -139,7 +139,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -170,7 +170,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db2_name }}' @@ -199,7 +199,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -231,7 +231,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -271,7 +271,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -308,7 +308,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - "{{ db1_name }}" @@ -348,7 +348,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - "{{ db4_name }}" @@ -384,11 +384,12 @@ # ========================================================================== # Dump existing databases + - name: Dump existing databases mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' @@ -398,13 +399,13 @@ target: '{{ dump1_file }}' register: dump_result -- name: assert successful completion of dump operation +- name: Assert successful completion of dump operation (existing database) assert: that: - dump_result is changed - dump_result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}'] -- name: run command to list databases like specified database name +- name: Run command to list databases like specified database name command: "{{ mysql_command }} \"-e show databases like 'database%'\"" register: mysql_result @@ -415,7 +416,7 @@ - "'{{ db2_name }}' in mysql_result.stdout" - "'{{ db3_name }}' in mysql_result.stdout" -- name: state dump - file name should exist +- name: State dump - file name should exist (dump1_file) file: name: '{{ dump1_file }}' state: file @@ -441,7 +442,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: all state: dump @@ -466,7 +467,7 @@ - "'{{ db4_name }}' not in mysql_result.stdout" - "'{{ db5_name }}' not in mysql_result.stdout" -- name: state dump - file name should exist +- name: state dump - file name should exist (dump2_file) file: name: '{{ dump2_file }}' state: file @@ -479,7 +480,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db2_name }}' @@ -509,7 +510,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db2_name }}' @@ -539,7 +540,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db2_name }}' @@ -569,7 +570,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db2_name }}' @@ -598,7 +599,7 @@ mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db1_name }}' diff --git a/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml b/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml index 6d904b9..5df8a1d 100644 --- a/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml +++ b/tests/integration/targets/test_mysql_db/tasks/state_dump_import.yml @@ -17,113 +17,116 @@ # along with Ansible. If not, see . # ============================================================ -- set_fact: +- name: Dump and Import | Set facts + set_fact: db_file_name: "{{ tmp_dir }}/{{ file }}" wrong_sql_file: "{{ tmp_dir }}/wrong.sql" dump_file1: "{{ tmp_dir }}/{{ file2 }}" dump_file2: "{{ tmp_dir }}/{{ file3 }}" db_user: "test" db_user_unsafe_password: "pass!word" - config_file: "/root/.my.cnf" + config_file: "{{ playbook_dir }}/root/.my.cnf" -- name: create custom config file +- name: Dump and Import | Create custom config file shell: 'echo "[client]" > {{ config_file }}' -- name: create user for test unsafe_login_password parameter +- name: Dump and Import | Create user for test unsafe_login_password parameter mysql_user: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_user }}' + host: '%' password: '{{ db_user_unsafe_password }}' priv: '*.*:ALL' state: present -- name: state dump/import - create database +- name: Dump and Import | State dump/import - create database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: present check_implicit_admin: yes -- name: create database +- name: Dump and Import | Create database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: present check_implicit_admin: no -- name: state dump/import - create table department +- name: Dump and Import | State dump/import - create table department command: "{{ mysql_command }} {{ db_name }} \"-e create table department(id int, name varchar(100))\"" -- name: state dump/import - create table employee +- name: Dump and Import | State dump/import - create table employee command: "{{ mysql_command }} {{ db_name }} \"-e create table employee(id int, name varchar(100))\"" -- name: state dump/import - insert data into table employee +- name: Dump and Import | State dump/import - insert data into table employee command: "{{ mysql_command }} {{ db_name }} \"-e insert into employee value(47,'Joe Smith')\"" -- name: state dump/import - insert data into table department +- name: Dump and Import | State dump/import - insert data into table department command: "{{ mysql_command }} {{ db_name }} \"-e insert into department value(2,'Engineering')\"" -- name: state dump/import - file name should not exist +- name: Dump and Import | State dump/import - file name should not exist file: name: '{{ db_file_name }}' state: absent -- name: database dump file1 should not exist +- name: Dump and Import | Database dump file1 should not exist file: name: '{{ dump_file1 }}' state: absent -- name: database dump file2 should not exist +- name: Dump and Import | Database dump file2 should not exist file: name: '{{ dump_file2 }}' state: absent -- name: state dump without department table. +- name: Dump and Import | State dump without department table. mysql_db: login_user: '{{ db_user }}' login_password: '{{ db_user_unsafe_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' unsafe_login_password: yes name: '{{ db_name }}' state: dump target: '{{ db_file_name }}' ignore_tables: - - "{{ db_name }}.department" + - "{{ db_name }}.department" force: yes master_data: 1 skip_lock_tables: yes - dump_extra_args: --skip-triggers + dump_extra_args: >- + --skip-triggers config_file: '{{ config_file }}' restrict_config_file: yes check_implicit_admin: no register: result -- name: assert successful completion of dump operation +- name: Dump and Import | Assert successful completion of dump operation assert: that: - result is changed - - result.executed_commands[0] is search("mysqldump --defaults-file={{ config_file }} --user={{ db_user }} --password=\*\*\*\*\*\*\*\* --force --host=127.0.0.1 --port={{ mysql_primary_port }} {{ db_name }} --skip-lock-tables --quick --ignore-table={{ db_name }}.department --master-data=1 --skip-triggers") + - result.executed_commands[0] is search(".department --master-data=1 --skip-triggers") -- name: state dump/import - file name should exist +- name: Dump and Import | State dump/import - file name should exist (db_file_name) file: name: '{{ db_file_name }}' state: file -- name: state dump with multiple databases in comma separated form. +- name: Dump and Import | State dump with multiple databases in comma separated form for MySQL. mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: "{{ db_name }},{{ db_name2 }}" state: dump @@ -131,22 +134,22 @@ check_implicit_admin: yes register: dump_result1 -- name: assert successful completion of dump operation (with multiple databases in comma separated form) +- name: Dump and Import | Assert successful completion of dump operation (with multiple databases in comma separated form) assert: that: - dump_result1 is changed - dump_result1.executed_commands[0] is search(" --user=root --password=\*\*\*\*\*\*\*\*") -- name: state dump - dump file1 should exist +- name: Dump and Import | State dump - dump file1 should exist file: name: '{{ dump_file1 }}' state: file -- name: state dump with multiple databases in list form via check_mode +- name: Dump and Import | State dump with multiple databases in list form via check_mode mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db_name }}' @@ -156,26 +159,26 @@ register: dump_result check_mode: yes -- name: assert successful completion of dump operation (with multiple databases in list form) via check mode +- name: Dump and Import | Assert successful completion of dump operation (with multiple databases in list form) via check mode assert: that: - dump_result is changed -- name: database dump file2 should not exist +- name: Dump and Import | Database dump file2 should not exist stat: path: '{{ dump_file2 }}' register: stat_result -- name: assert that check_mode does not create dump file for databases +- name: Dump and Import | Assert that check_mode does not create dump file for databases assert: that: - stat_result.stat.exists is defined and not stat_result.stat.exists -- name: state dump with multiple databases in list form. +- name: Dump and Import | State dump with multiple databases in list form. mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: - '{{ db_name }}' @@ -184,39 +187,39 @@ target: '{{ dump_file2 }}' register: dump_result2 -- name: assert successful completion of dump operation (with multiple databases in list form) +- name: Dump and Import | Assert successful completion of dump operation (with multiple databases in list form) assert: that: - dump_result2 is changed -- name: state dump - dump file2 should exist +- name: Dump and Import | State dump - dump file2 should exist file: name: '{{ dump_file2 }}' state: file -- name: state dump/import - remove database +- name: Dump and Import | State dump/import - remove database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: absent -- name: remove database +- name: Dump and Import | Remove database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: absent -- name: test state=import to restore the database of type {{ format_type }} (expect changed=true) +- name: Dump and Import | Test state=import to restore the database of type {{ format_type }} (expect changed=true) mysql_db: login_user: '{{ db_user }}' login_password: '{{ db_user_unsafe_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' unsafe_login_password: yes name: '{{ db_name }}' @@ -225,20 +228,20 @@ use_shell: yes register: result -- name: show the tables +- name: Dump and Import | Show the tables command: "{{ mysql_command }} {{ db_name }} \"-e show tables\"" register: result -- name: assert that the department table is absent. +- name: Dump and Import | Assert that the department table is absent. assert: that: - "'department' not in result.stdout" -- name: test state=import to restore a database from multiple database dumped file1 +- name: Dump and Import | Test state=import to restore a database from multiple database dumped file1 mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: import @@ -246,34 +249,34 @@ use_shell: no register: import_result -- name: assert output message restored a database from dump file1 +- name: Dump and Import | Assert output message restored a database from dump file1 assert: that: - import_result is changed -- name: remove database +- name: Dump and Import | Remove database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: absent -- name: run command to list databases +- name: Dump and Import | Run command to list databases command: "{{ mysql_command }} \"-e show databases like 'data%'\"" register: mysql_result -- name: assert that db_name2 database does not exist +- name: Dump and Import | Assert that db_name2 database does not exist assert: that: - "'{{ db_name2 }}' not in mysql_result.stdout" -- name: test state=import to restore a database from dumped file2 (check mode) +- name: Dump and Import | Test state=import to restore a database from dumped file2 (check mode) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: import @@ -281,96 +284,96 @@ register: check_import_result check_mode: yes -- name: assert output message restored a database from dump file2 (check mode) +- name: Dump and Import | Assert output message restored a database from dump file2 (check mode) assert: that: - check_import_result is changed -- name: run command to list databases +- name: Dump and Import | Run command to list databases command: "{{ mysql_command }} \"-e show databases like 'data%'\"" register: mysql_result -- name: assert that db_name2 database does not exist (check mode) +- name: Dump and Import | Assert that db_name2 database does not exist (check mode) assert: that: - "'{{ db_name2 }}' not in mysql_result.stdout" -- name: test state=import to restore a database from multiple database dumped file2 +- name: Dump and Import | Test state=import to restore a database from multiple database dumped file2 mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name2 }}' state: import target: '{{ dump_file2 }}' register: import_result2 -- name: assert output message restored a database from dump file2 +- name: Dump and Import | Assert output message restored a database from dump file2 assert: that: - import_result2 is changed - import_result2.db_list == ['{{ db_name2 }}'] -- name: run command to list databases +- name: Dump and Import | Run command to list databases command: "{{ mysql_command }} \"-e show databases like 'data%'\"" register: mysql_result -- name: assert that db_name2 database does exist after import +- name: Dump and Import | Assert that db_name2 database does exist after import assert: that: - "'{{ db_name2 }}' in mysql_result.stdout" -- name: test state=dump to backup the database of type {{ format_type }} (expect changed=true) +- name: Dump and Import | Test state=dump to backup the database of type {{ format_type }} (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: dump target: '{{ db_file_name }}' register: result -- name: assert output message backup the database +- name: Dump and Import | Assert output message backup the database assert: that: - result is changed - "result.db =='{{ db_name }}'" -# - name: assert database was backed up successfully +# - name: Dump and Import | Assert database was backed up successfully # command: "file {{ db_file_name }}" # register: result # -# - name: assert file format type +# - name: Dump and Import | Assert file format type # assert: # that: # - "'{{ format_msg_type }}' in result.stdout" -- name: update database table employee +- name: Dump and Import | Update database table employee command: "{{ mysql_command }} {{ db_name }} \"-e update employee set name='John Doe' where id=47\"" -- name: test state=import to restore the database of type {{ format_type }} (expect changed=true) +- name: Dump and Import | Test state=import to restore the database of type {{ format_type }} (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: import target: '{{ db_file_name }}' register: result -- name: assert output message restore the database +- name: Dump and Import | Assert output message restore the database assert: that: - result is changed -- name: select data from table employee +- name: Dump and Import | Select data from table employee command: "{{ mysql_command }} {{ db_name }} \"-e select * from employee\"" register: result -- name: assert data in database is from the restore database +- name: Dump and Import | Assert data in database is from the restore database assert: that: - "'47' in result.stdout" @@ -380,14 +383,14 @@ # Test ``force`` parameter ########################## -- name: create wrong sql file +- name: Dump and Import | Create wrong sql file shell: echo 'CREATE TABLE hello (id int); CREATE ELBAT ehlo (int id);' >> '{{ wrong_sql_file }}' -- name: try to import without force parameter, must fail +- name: Dump and Import | Try to import without force parameter, must fail mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: import @@ -400,11 +403,11 @@ that: - result is failed -- name: try to import with force parameter +- name: Dump and Import | Try to import with force parameter mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: import @@ -420,40 +423,24 @@ # Clean up ########## -- name: remove database name +- name: Dump and Import | Clean up databases mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' - name: '{{ db_name }}' + name: '{{ item }}' state: absent + loop: + - '{{ db_name }}' + - '{{ db_name2 }}' -- name: remove database - mysql_db: - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - name: '{{ db_name2 }}' - state: absent - -- name: remove file name +- name: Dump and Import | Clean up files file: - name: '{{ db_file_name }}' - state: absent - -- name: remove file name - file: - name: '{{ wrong_sql_file }}' - state: absent - -- name: remove dump file1 - file: - name: '{{ dump_file1 }}' - state: absent - -- name: remove dump file2 - file: - name: '{{ dump_file2 }}' + name: '{{ item }}' state: absent + loop: + - '{{ db_file_name }}' + - '{{ wrong_sql_file }}' + - '{{ dump_file1 }}' + - '{{ dump_file2 }}' diff --git a/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml b/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml index 5b6e871..12633f2 100644 --- a/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml +++ b/tests/integration/targets/test_mysql_db/tasks/state_present_absent.yml @@ -1,3 +1,4 @@ +--- # test code for mysql_db module with database name containing special chars # This file is part of Ansible @@ -16,75 +17,75 @@ # along with Ansible. If not, see . # ============================================================ -- name: remove database if it exists +- name: State Present Absent | Remove database if it exists command: > "{{ mysql_command }} -sse 'DROP DATABASE IF EXISTS {{ db_name }}'" ignore_errors: true -- name: make sure the test database is not there +- name: State Present Absent | Make sure the test database is not there command: "{{ mysql_command }} {{ db_name }}" register: mysql_db_check failed_when: "'1049' not in mysql_db_check.stderr" -- name: test state=present for a database name (expect changed=true) +- name: State Present Absent | Test state=present for a database name (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: present register: result -- name: assert output message that database exist +- name: State Present Absent | Assert output message that database exist assert: that: - result is changed - result.db == '{{ db_name }}' - result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"] -- name: run command to test state=present for a database name (expect db_name in stdout) +- name: State Present Absent | Run command to test state=present for a database name (expect db_name in stdout) command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database exist +- name: State Present Absent | Assert database exist assert: that: - "'{{ db_name }}' in result.stdout" # ============================================================ -- name: test state=absent for a database name (expect changed=true) +- name: State Present Absent | Test state=absent for a database name (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_name }}' state: absent register: result -- name: assert output message that database does not exist +- name: State Present Absent | Assert output message that database does not exist assert: that: - result is changed - result.db == '{{ db_name }}' - result.executed_commands == ["DROP DATABASE `{{ db_name }}`"] -- name: run command to test state=absent for a database name (expect db_name not in stdout) +- name: State Present Absent | Run command to test state=absent for a database name (expect db_name not in stdout) command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database does not exist +- name: State Present Absent | Assert database does not exist assert: that: - "'{{ db_name }}' not in result.stdout" # ============================================================ -- name: test mysql_db encoding param not valid - issue 8075 +- name: State Present Absent | Test mysql_db encoding param not valid - issue 8075 mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: datanotvalid state: present @@ -92,7 +93,7 @@ register: result ignore_errors: true -- name: assert test mysql_db encoding param not valid - issue 8075 (failed=true) +- name: State Present Absent | Assert test mysql_db encoding param not valid - issue 8075 (failed=true) assert: that: - result is failed @@ -100,201 +101,202 @@ - "'Unknown character set' in result.msg" # ============================================================ -- name: test mysql_db using a valid encoding utf8 (expect changed=true) +- name: State Present Absent | Test mysql_db using a valid encoding utf8 (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: 'en{{ db_name }}' state: present encoding: utf8 register: result -- name: assert output message created a database +- name: State Present Absent | Assert output message created a database assert: that: - result is changed - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"] -- name: test database was created +- name: State Present Absent | Test database was created command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\"" register: result -- name: assert created database is of encoding utf8 +- name: State Present Absent | Assert created database is of encoding utf8 assert: that: - "'utf8' in result.stdout" -- name: remove database +- name: State Present Absent | Remove database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: 'en{{ db_name }}' state: absent # ============================================================ -- name: test mysql_db using valid encoding binary (expect changed=true) +- name: State Present Absent | Test mysql_db using valid encoding binary (expect changed=true) mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: 'en{{ db_name }}' state: present encoding: binary register: result -- name: assert output message that database was created +- name: State Present Absent | Assert output message that database was created assert: that: - result is changed - result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"] -- name: run command to test database was created +- name: State Present Absent | Run command to test database was created command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\"" register: result -- name: assert created database is of encoding binary +- name: State Present Absent | Assert created database is of encoding binary assert: that: - "'binary' in result.stdout" -- name: remove database +- name: State Present Absent | Remove database mysql_db: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: 'en{{ db_name }}' state: absent # ============================================================ -- name: create user1 to access database dbuser1 +- name: State Present Absent | Create user1 to access database dbuser1 mysql_user: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: user1 + host: '%' password: 'Hfd6fds^dfA8Ga' priv: '*.*:ALL' state: present -- name: create database dbuser1 using user1 +- name: State Present Absent | Create database dbuser1 using user1 mysql_db: login_user: user1 login_password: 'Hfd6fds^dfA8Ga' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_user1 }}' state: present register: result -- name: assert output message that database was created +- name: State Present Absent | Assert output message that database was created assert: that: - result is changed -- name: run command to test database was created using user1 +- name: State Present Absent | Run command to test database was created using user1 command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database exist +- name: State Present Absent | Assert database exist assert: that: - "'{{ db_user1 }}' in result.stdout" # ============================================================ -- name: create user2 to access database with privilege select only +- name: State Present Absent | Create user2 to access database with privilege select only mysql_user: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: user2 password: 'kjsfd&F7safjad' priv: '*.*:SELECT' state: present -- name: create database dbuser2 using user2 with no privilege to create (expect failed=true) +- name: State Present Absent | Create database dbuser2 using user2 with no privilege to create (expect failed=true) mysql_db: login_user: user2 login_password: 'kjsfd&F7safjad' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_user2 }}' state: present register: result ignore_errors: true -- name: assert output message that database was not created using dbuser2 +- name: State Present Absent | Assert output message that database was not created using dbuser2 assert: that: - result is failed - "'Access denied' in result.msg" -- name: run command to test that database was not created +- name: State Present Absent | Run command to test that database was not created command: "{{ mysql_command }} -e \"show databases like '{{ db_user2 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database does not exist +- name: State Present Absent | Assert database does not exist assert: that: - "'{{ db_user2 }}' not in result.stdout" # ============================================================ -- name: delete database using user2 with no privilege to delete (expect failed=true) +- name: State Present Absent | Delete database using user2 with no privilege to delete (expect failed=true) mysql_db: login_user: user2 login_password: 'kjsfd&F7safjad' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_user1 }}' state: absent register: result ignore_errors: true -- name: assert output message that database was not deleted using dbuser2 +- name: State Present Absent | Assert output message that database was not deleted using dbuser2 assert: that: - result is failed - "'Access denied' in result.msg" -- name: run command to test database was not deleted +- name: State Present Absent | Run command to test database was not deleted command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database still exist +- name: State Present Absent | Assert database still exist assert: that: - "'{{ db_user1 }}' in result.stdout" # ============================================================ -- name: delete database using user1 with all privilege to delete a database (expect changed=true) +- name: State Present Absent | Delete database using user1 with all privilege to delete a database (expect changed=true) mysql_db: login_user: user1 login_password: 'Hfd6fds^dfA8Ga' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: '{{ db_user1 }}' state: absent register: result ignore_errors: true -- name: assert output message that database was deleted using user1 +- name: State Present Absent | Assert output message that database was deleted using user1 assert: that: - result is changed - result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"] -- name: run command to test database was deleted using user1 +- name: State Present Absent | Run command to test database was deleted using user1 command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\"" register: result -- name: assert database does not exist +- name: State Present Absent | Assert database does not exist assert: that: - "'{{ db_user1 }}' not in result.stdout" diff --git a/tests/integration/targets/test_mysql_info/defaults/main.yml b/tests/integration/targets/test_mysql_info/defaults/main.yml index e1b932c..e1cd880 100644 --- a/tests/integration/targets/test_mysql_info/defaults/main.yml +++ b/tests/integration/targets/test_mysql_info/defaults/main.yml @@ -2,7 +2,7 @@ # defaults file for test_mysql_info mysql_user: root mysql_password: msandbox -mysql_host: 127.0.0.1 +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 db_name: data diff --git a/tests/integration/targets/test_mysql_info/meta/main.yml b/tests/integration/targets/test_mysql_info/meta/main.yml index a7ace5d..4be5f58 100644 --- a/tests/integration/targets/test_mysql_info/meta/main.yml +++ b/tests/integration/targets/test_mysql_info/meta/main.yml @@ -1,3 +1,4 @@ +--- dependencies: - - setup_mysql + - setup_controller - setup_remote_tmp_dir diff --git a/tests/integration/targets/test_mysql_info/tasks/connector_info.yml b/tests/integration/targets/test_mysql_info/tasks/connector_info.yml index 349ccef..f7890b0 100644 --- a/tests/integration/targets/test_mysql_info/tasks/connector_info.yml +++ b/tests/integration/targets/test_mysql_info/tasks/connector_info.yml @@ -2,7 +2,6 @@ # Added in 1.5.0, 2.4.0 and 3.6.0 in # https://github.com/ansible-collections/community.mysql/pull/497 -# TODO: Refactor in PR490. - name: Connector info | Assert connector_name exists and has expected values ansible.builtin.assert: that: @@ -15,18 +14,17 @@ {{ result.connector_name | d('Unknown')}} which is different than expected pymysql or MySQLdb -# TODO: Refactor in PR490. - name: Connector info | Assert connector_version exists and has expected values ansible.builtin.assert: that: - result.connector_version is defined - > result.connector_version == 'Unknown' - or result.connector_version is version(connector_ver, '==') + or result.connector_version is version(connector_version, '==') success_msg: >- Assertions passed, result.connector_version is {{ result.connector_version }} fail_msg: >- Assertion failed, result.connector_version is {{ result.connector_version }} which is different than expected - {{ connector_ver }} + {{ connector_version }} diff --git a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml index 068fbb3..1fbf3a9 100644 --- a/tests/integration/targets/test_mysql_info/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_info/tasks/issue-28.yml @@ -1,7 +1,4 @@ --- -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - name: set fact tls_enabled command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" @@ -13,7 +10,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: @@ -30,6 +27,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -37,6 +35,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" tls_requires: SSL: @@ -46,7 +45,7 @@ filter: version login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem register: result @@ -55,19 +54,21 @@ - assert: that: - result is failed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' - assert: that: - result is succeeded - when: connector_name is not search('pymysql') + when: + - connector_name != 'pymysql' - name: attempt connection with newly created user ignoring hostname mysql_info: filter: version login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem check_hostname: no @@ -82,5 +83,5 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' - host: 127.0.0.1 + host_all: true state: absent diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml index a5428e3..a01f915 100644 --- a/tests/integration/targets/test_mysql_info/tasks/main.yml +++ b/tests/integration/targets/test_mysql_info/tasks/main.yml @@ -1,3 +1,4 @@ +--- #################################################################### # WARNING: These are designed specifically for Ansible tests # # and should not be used as examples of how to write Ansible roles # @@ -24,14 +25,14 @@ - name: mysql_info - create default config file template: src: my.cnf.j2 - dest: /root/.my.cnf + dest: "{{ playbook_dir }}/root/.my.cnf" mode: '0400' # Create non-default MySQL config file with credentials - name: mysql_info - create non-default config file template: src: my.cnf.j2 - dest: /root/non-default_my.cnf + dest: "{{ playbook_dir }}/root/non-default_my.cnf" mode: '0400' ############### @@ -43,17 +44,18 @@ login_user: '{{ mysql_user }}' login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' + config_file: "{{ playbook_dir }}/root/.my.cnf" register: result - assert: that: - - result is not changed - - "mysql_version in result.version.full or mariadb_version in result.version.full" - - result.settings != {} - - result.global_status != {} - - result.databases != {} - - result.engines != {} - - result.users != {} + - result is not changed + - db_version in result.version.full + - result.settings != {} + - result.global_status != {} + - result.databases != {} + - result.engines != {} + - result.users != {} - name: mysql_info - Test connector informations display ansible.builtin.import_tasks: @@ -65,7 +67,7 @@ login_user: '{{ mysql_user }}' login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' - config_file: /root/non-default_my.cnf + config_file: "{{ playbook_dir }}/root/non-default_my.cnf" register: result - assert: @@ -78,9 +80,9 @@ file: path: '{{ item }}' state: absent - with_items: - - /root/.my.cnf - - /root/non-default_my.cnf + loop: + - "{{ playbook_dir }}/.my.cnf" + - "{{ playbook_dir }}/non-default_my.cnf" # Access with password - name: mysql_info - check access with password diff --git a/tests/integration/targets/test_mysql_query/defaults/main.yml b/tests/integration/targets/test_mysql_query/defaults/main.yml index 4ee25ff..6befdcf 100644 --- a/tests/integration/targets/test_mysql_query/defaults/main.yml +++ b/tests/integration/targets/test_mysql_query/defaults/main.yml @@ -1,5 +1,6 @@ mysql_user: root mysql_password: msandbox +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 db_name: data diff --git a/tests/integration/targets/test_mysql_query/meta/main.yml b/tests/integration/targets/test_mysql_query/meta/main.yml index ce08dc4..01ee3db 100644 --- a/tests/integration/targets/test_mysql_query/meta/main.yml +++ b/tests/integration/targets/test_mysql_query/meta/main.yml @@ -1,2 +1,3 @@ +--- dependencies: -- setup_mysql + - setup_controller diff --git a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml index 43eda1a..f7d8ba1 100644 --- a/tests/integration/targets/test_mysql_query/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_query/tasks/issue-28.yml @@ -1,7 +1,4 @@ --- -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - name: set fact tls_enabled command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" @@ -13,7 +10,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: @@ -30,6 +27,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -37,6 +35,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" tls_requires: SSL: @@ -46,7 +45,7 @@ query: 'SHOW DATABASES' login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem register: result @@ -55,19 +54,21 @@ - assert: that: - result is failed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' - assert: that: - result is succeeded - when: connector_name is not search('pymysql') + when: + - connector_name != 'pymysql' - name: attempt connection with newly created user ignoring hostname mysql_query: query: 'SHOW DATABASES' login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem check_hostname: no @@ -82,5 +83,5 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' - host: 127.0.0.1 + host: "%" state: absent diff --git a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml index cbb7b53..d97c554 100644 --- a/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml +++ b/tests/integration/targets/test_mysql_query/tasks/mysql_query_initial.yml @@ -1,3 +1,4 @@ +--- # Test code for mysql_query module # Copyright: (c) 2020, Andrew Klychkov (@Andersson007) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -5,7 +6,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: @@ -16,7 +17,8 @@ query: 'CREATE DATABASE {{ test_db }}' register: result - - assert: + - name: Assert that create db test_db is changed and returns expected query + assert: that: - result is changed - result.executed_queries == ['CREATE DATABASE {{ test_db }}'] @@ -28,7 +30,8 @@ query: 'CREATE TABLE {{ test_table1 }} (id int)' register: result - - assert: + - name: Assert that create table test_table1 is changed and returns expected query + assert: that: - result is changed - result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)'] @@ -38,12 +41,13 @@ <<: *mysql_params login_db: '{{ test_db }}' query: - - 'INSERT INTO {{ test_table1 }} VALUES (1), (2)' - - 'INSERT INTO {{ test_table1 }} VALUES (3)' + - 'INSERT INTO {{ test_table1 }} VALUES (1), (2)' + - 'INSERT INTO {{ test_table1 }} VALUES (3)' single_transaction: yes register: result - - assert: + - name: Assert that inserting test data is changed and returns expected query and results + assert: that: - result is changed - result.rowcount == [2, 1] @@ -56,7 +60,8 @@ query: 'SELECT * FROM {{ test_table1 }}' register: result - - assert: + - name: Assert that query data in test_table1 is not changed and returns expected query and results + assert: that: - result is not changed - result.executed_queries == ['SELECT * FROM {{ test_table1 }}'] @@ -74,7 +79,8 @@ - 1 register: result - - assert: + - name: Assert that query data in test_table1 using positional args is not changed and returns expected query and results + assert: that: - result is not changed - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] @@ -90,7 +96,8 @@ some_id: 1 register: result - - assert: + - name: Assert that query data in test_table1 using named args is not changed and returns expected query and results + assert: that: - result is not changed - result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"] @@ -107,7 +114,8 @@ new_id: 0 register: result - - assert: + - name: Assert that update data in test_table1 is changed and returns the expected query + assert: that: - result is changed - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] @@ -122,7 +130,8 @@ some_id: 1 register: result - - assert: + - name: Assert that query that check the prev update is not changed and returns the expected query with id = 1 + assert: that: - result is not changed - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1'] @@ -137,7 +146,8 @@ some_id: 0 register: result - - assert: + - name: Assert that query that check the prev update is not changed and returns the expected query with id = 0 + assert: that: - result is not changed - result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0'] @@ -153,7 +163,8 @@ new_id: 0 register: result - - assert: + - name: Assert that update data in test_table1 again is not changed and returns expected query + assert: that: - result is not changed - result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1'] @@ -168,7 +179,8 @@ - 'SELECT * FROM {{ test_table1 }} WHERE id = 0' register: result - - assert: + - name: Assert that delete data from test_table1 is changed an returns expected query + assert: that: - result is changed - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0'] @@ -181,7 +193,8 @@ query: 'DELETE FROM {{ test_table1 }} WHERE id = 0' register: result - - assert: + - name: Assert that delete data from test_table1 again is not changed and returns expected query + assert: that: - result is not changed - result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0'] @@ -192,11 +205,12 @@ <<: *mysql_params login_db: '{{ test_db }}' query: - - 'TRUNCATE {{ test_table1 }}' - - 'SELECT * FROM {{ test_table1 }}' + - 'TRUNCATE {{ test_table1 }}' + - 'SELECT * FROM {{ test_table1 }}' register: result - - assert: + - name: Assert that truncate test_table1 is changed and returns expected query + assert: that: - result is changed - result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}'] @@ -209,7 +223,8 @@ query: 'RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}' register: result - - assert: + - name: Assert that rename table test_table1 is changed and returns expected query + assert: that: - result is changed - result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}'] @@ -223,7 +238,8 @@ register: result ignore_errors: yes - - assert: + - name: Assert that query old table is failed + assert: that: - result is failed @@ -234,7 +250,8 @@ query: 'SELECT * FROM {{ test_table2 }}' register: result - - assert: + - name: Assert that query new table succeed and returns 0 row + assert: that: - result.rowcount == [0] @@ -257,7 +274,8 @@ query: 'SELECT id, story FROM {{ test_table3 }}' register: result - - assert: + - name: Assert that select from test_table3 returns 2 rows + assert: that: - result.rowcount == [2] @@ -269,7 +287,8 @@ register: result ignore_errors: yes - - assert: + - name: Assert that pass wrong query type is failed + assert: that: - result is failed - result.msg is search('the query option value must be a string or list') @@ -284,7 +303,8 @@ register: result ignore_errors: yes - - assert: + - name: Assert that pass wrong query element is failed + assert: that: - result is failed - result.msg is search('the elements in query list must be strings') @@ -303,7 +323,8 @@ single_transaction: yes register: result - - assert: + - name: Assert that insert test data using replace statement is changed + assert: that: - result is changed - result.rowcount == [1] @@ -339,20 +360,24 @@ register: result # Issue https://github.com/ansible-collections/community.mysql/issues/268 - - assert: + - name: Assert that create table IF NOT EXISTS is not changed with pymysql + assert: that: # PyMySQL driver throws a warning, so the following is correct - result is not changed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' # Issue https://github.com/ansible-collections/community.mysql/issues/268 - - assert: + - name: Assert that create table IF NOT EXISTS is changed with mysqlclient + assert: that: - # mysqlclient driver throws nothing, so it's impossible to figure out - # if the state was changed or not. - # We assume that it was for DDL queryes by default in the code + # Mysqlclient 2.0.1, driver throws nothing with mysql, so it's + # impossible to figure out if the state was changed or not. + # We assume that it was for DDL queries by default in the code - result is changed - when: connector_name is search('mysqlclient') + when: + - connector_name == 'mysqlclient' - name: Drop db {{ test_db }} mysql_query: @@ -360,7 +385,15 @@ query: 'DROP DATABASE {{ test_db }}' register: result - - assert: + - name: Assert that drop database is changed and returns expected query + assert: that: - result is changed - result.executed_queries == ['DROP DATABASE {{ test_db }}'] + + always: + + - name: Clean up test_db + mysql_query: + <<: *mysql_params + query: 'DROP DATABASE IF EXISTS {{ test_db }}' diff --git a/tests/integration/targets/test_mysql_replication/defaults/main.yml b/tests/integration/targets/test_mysql_replication/defaults/main.yml index fefcf29..192a151 100644 --- a/tests/integration/targets/test_mysql_replication/defaults/main.yml +++ b/tests/integration/targets/test_mysql_replication/defaults/main.yml @@ -1,6 +1,6 @@ mysql_user: root mysql_password: msandbox -mysql_host: 127.0.0.1 +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 mysql_replica1_port: 3308 mysql_replica2_port: 3309 diff --git a/tests/integration/targets/test_mysql_replication/meta/main.yml b/tests/integration/targets/test_mysql_replication/meta/main.yml index 36e111c..01ee3db 100644 --- a/tests/integration/targets/test_mysql_replication/meta/main.yml +++ b/tests/integration/targets/test_mysql_replication/meta/main.yml @@ -1,3 +1,3 @@ --- dependencies: -- setup_mysql + - setup_controller diff --git a/tests/integration/targets/test_mysql_replication/tasks/issue-265.yml b/tests/integration/targets/test_mysql_replication/tasks/issue-265.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml index da607ce..ea17f35 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/issue-28.yml @@ -1,7 +1,4 @@ --- -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - name: set fact tls_enabled command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\"" @@ -13,7 +10,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: @@ -30,6 +27,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -47,7 +45,7 @@ mode: getmaster login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem register: result @@ -56,19 +54,21 @@ - assert: that: - result is failed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' - assert: that: - result is succeeded - when: connector_name is not search('pymysql') + when: + - connector_name != 'pymysql' - name: attempt connection with newly created user ignoring hostname mysql_replication: mode: getmaster login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem check_hostname: no @@ -83,5 +83,5 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' - host: 127.0.0.1 + host: '{{ gateway_addr }}' state: absent diff --git a/tests/integration/targets/test_mysql_replication/tasks/main.yml b/tests/integration/targets/test_mysql_replication/tasks/main.yml index eae58c0..491db34 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/main.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/main.yml @@ -15,7 +15,8 @@ # Tests of channel parameter: - import_tasks: mysql_replication_channel.yml when: - - install_type == 'mysql' # FIXME: mariadb introduces FOR CHANNEL in 10.7 + - db_engine == 'mysql' # FIXME: mariadb introduces FOR CHANNEL in 10.7 + - mysql8022_and_higher == true # FIXME: mysql 5.7 should work, but our tets fails, why? # Tests of resetmaster mode: - import_tasks: mysql_replication_resetmaster_mode.yml diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_channel.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_channel.yml index 1bbc1bc..76ab423 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_channel.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_channel.yml @@ -1,3 +1,4 @@ +--- # Copyright: (c) 2019, Andrew Klychkov (@Andersson007) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -5,7 +6,7 @@ mysql_params: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' block: # Get master log file and log pos: diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml index 7899e1a..38169ae 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml @@ -1,3 +1,4 @@ +--- # Copyright: (c) 2019, Andrew Klychkov (@Andersson007) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -5,16 +6,9 @@ mysql_params: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' block: - - name: find out the database version - mysql_info: - <<: *mysql_params - login_port: '{{ mysql_primary_port }}' - filter: version - register: db - - name: Set mysql8022_and_higher set_fact: mysql8022_and_higher: false @@ -23,21 +17,31 @@ set_fact: mysql8022_and_higher: true when: - - db.version.major > 8 or (db.version.major == 8 and db.version.minor > 0) or (db.version.major == 8 and db.version.minor == 0 and db.version.release >= 22) - - install_type == 'mysql' + - db_engine == 'mysql' + - db_version is version('8.0.22', '>=') - - name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --protocol=tcp" - - # Preparation: + # We use iF NOT EXISTS because the GITHUB Action: + # "ansible-community/ansible-test-gh-action" uses "--retry-on-error". + # If test_mysql_replication fails, test will run again an without the IF + # NOT EXISTS, we see "Error 1396 (HY000): Operation CREATE USER failed..." + # which is misleading. - name: Create user for mysql replication - shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}" - when: install_type == 'mysql' + shell: + "echo \"CREATE USER IF NOT EXISTS \ + '{{ replication_user }}'@'{{ mysql_host }}' \ + IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; \ + GRANT REPLICATION SLAVE ON *.* TO \ + '{{ replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}" + when: db_engine == 'mysql' - name: Create user for mariadb replication - shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}" - when: install_type == 'mariadb' + shell: + "echo \"CREATE USER IF NOT EXISTS \ + '{{ replication_user }}'@'{{ mysql_host }}' \ + IDENTIFIED BY '{{ replication_pass }}'; \ + GRANT REPLICATION SLAVE ON *.* TO \ + '{{ replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}" + when: db_engine == 'mariadb' - name: Create test database mysql_db: @@ -47,13 +51,31 @@ name: '{{ test_db }}' - name: Dump all databases from the primary - shell: 'mysqldump -u{{ mysql_user }} -p{{ mysql_password }} -h{{ mysql_host }} --protocol=tcp -P{{ mysql_primary_port }} --all-databases --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats --master-data=2 > {{ dump_path }}' + shell: + cmd: >- + mysqldump + -u{{ mysql_user }} + -p{{ mysql_password }} + -h{{ mysql_host }} + -P{{ mysql_primary_port }} + --protocol=tcp + --all-databases + --ignore-table=mysql.innodb_index_stats + --ignore-table=mysql.innodb_table_stats + --master-data=2 + > {{ dump_path }} - name: Restore the dump to replica1 - shell: '{{ mysql_command }} -P{{ mysql_replica1_port }} < {{ dump_path }}' + shell: + cmd: >- + {{ mysql_command_wo_port }} + -P{{ mysql_replica1_port }} < {{ dump_path }} - name: Restore the dump to replica2 - shell: '{{ mysql_command }} -P{{ mysql_replica2_port }} < {{ dump_path }}' + shell: + cmd: >- + {{ mysql_command_wo_port }} + -P{{ mysql_replica2_port }} < {{ dump_path }} # Test getmaster mode: - name: Get master status @@ -63,7 +85,8 @@ mode: getmaster register: mysql_primary_status - - assert: + - name: Assert that primary is in expected state + assert: that: - mysql_primary_status.Is_Master == true - mysql_primary_status.Position != 0 @@ -79,9 +102,10 @@ register: result ignore_errors: yes - - assert: + - name: Assert that startreplica is failed + assert: that: - - result is failed + - result is failed # Test startreplica doesn't fail if fail_on_error: no - name: Start replica and fail without propagating it to ansible as we were asked not to @@ -92,9 +116,10 @@ fail_on_error: no register: result - - assert: + - name: Assert that startreplica succeeded + assert: that: - - result is not failed + - result is not failed # Test startreplica doesn't fail if there is no fail_on_error. # This is suboptimal because nothing happens, but it's the old behavior. @@ -105,9 +130,10 @@ mode: startreplica register: result - - assert: + - name: Assert that start replica succeeded again + assert: that: - - result is not failed + - result is not failed # Test changemaster mode: # master_ssl_ca will be set as '' to check the module's behaviour for #23976, @@ -126,7 +152,8 @@ master_ssl_ca: '' register: result - - assert: + - name: Assert that changeprimmary is changed and return expected query + assert: that: - result is changed - result.queries == ["CHANGE MASTER TO MASTER_HOST='{{ mysql_host }}',MASTER_USER='{{ replication_user }}',MASTER_PASSWORD='********',MASTER_PORT={{ mysql_primary_port }},MASTER_LOG_FILE='{{ mysql_primary_status.File }}',MASTER_LOG_POS={{ mysql_primary_status.Position }},MASTER_SSL_CA=''"] @@ -139,10 +166,11 @@ mode: startreplica register: result - - assert: + - name: Assert that startreplica is changed and returns expected query + assert: that: - - result is changed - - result.queries == ["START SLAVE"] or result.queries == ["START REPLICA"] + - result is changed + - result.queries == ["START SLAVE"] or result.queries == ["START REPLICA"] # Test getreplica mode: - name: Get replica status using deprecated getslave choice @@ -152,7 +180,8 @@ mode: getslave register: replica_status - - assert: + - name: Assert that getreplica returns expected values for MySQL older than 8.0.22 and Mariadb + assert: that: - replica_status.Is_Slave == true - replica_status.Master_Host == '{{ mysql_host }}' @@ -163,7 +192,8 @@ - replica_status is not changed when: mysql8022_and_higher == false - - assert: + - name: Assert that getreplica returns expected values for MySQL newer than 8.0.22 + assert: that: - replica_status.Is_Slave == true - replica_status.Source_Host == '{{ mysql_host }}' @@ -176,10 +206,10 @@ # Create test table and add data to it: - name: Create test table - shell: "echo \"CREATE TABLE {{ test_table }} (id int);\" | {{ mysql_command }} -P{{ mysql_primary_port }} {{ test_db }}" + shell: "echo \"CREATE TABLE {{ test_table }} (id int);\" | {{ mysql_command_wo_port }} -P{{ mysql_primary_port }} {{ test_db }}" - name: Insert data - shell: "echo \"INSERT INTO {{ test_table }} (id) VALUES (1), (2), (3); FLUSH LOGS;\" | {{ mysql_command }} -P{{ mysql_primary_port }} {{ test_db }}" + shell: "echo \"INSERT INTO {{ test_table }} (id) VALUES (1), (2), (3); FLUSH LOGS;\" | {{ mysql_command_wo_port }} -P{{ mysql_primary_port }} {{ test_db }}" - name: Small pause to be sure the bin log, which was flushed previously, reached the replica ansible.builtin.wait_for: @@ -195,14 +225,16 @@ # mysql_primary_status.Position is not actual and it has been changed by the prev step, # so replica_status.Exec_Master_Log_Pos must be different: - - assert: + - name: Assert that getreplica Log_Pos is different for MySQL older than 8.0.22 and MariaDB + assert: that: - - replica_status.Exec_Master_Log_Pos != mysql_primary_status.Position + - replica_status.Exec_Master_Log_Pos != mysql_primary_status.Position when: mysql8022_and_higher == false - - assert: + - name: Assert that getreplica Log_Pos is different for MySQL newer than 8.0.22 + assert: that: - - replica_status.Exec_Source_Log_Pos != mysql_primary_status.Position + - replica_status.Exec_Source_Log_Pos != mysql_primary_status.Position when: mysql8022_and_higher == true - name: Start replica that is already running @@ -214,7 +246,8 @@ register: result # mysqlclient 2.0.1 always return "changed" - - assert: + - name: Assert that startreplica is not changed + assert: that: - result is not changed when: @@ -228,10 +261,11 @@ mode: stopslave register: result - - assert: + - name: Assert that stopreplica is changed and returns expected query + assert: that: - - result is changed - - result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"] + - result is changed + - result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"] - name: Pause for 2 seconds to let the replication stop ansible.builtin.wait_for: @@ -247,7 +281,8 @@ fail_on_error: true register: result - - assert: + - name: Assert that stopreplica is not changed + assert: that: - result is not changed when: diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_master_delay.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_master_delay.yml index 94a10b2..10f43af 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_master_delay.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_master_delay.yml @@ -5,7 +5,7 @@ mysql_params: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' block: diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetmaster_mode.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetmaster_mode.yml index 223e325..84a833d 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetmaster_mode.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetmaster_mode.yml @@ -5,7 +5,7 @@ mysql_params: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' block: diff --git a/tests/integration/targets/test_mysql_user/defaults/main.yml b/tests/integration/targets/test_mysql_user/defaults/main.yml index 5cf9074..a87914c 100644 --- a/tests/integration/targets/test_mysql_user/defaults/main.yml +++ b/tests/integration/targets/test_mysql_user/defaults/main.yml @@ -2,7 +2,7 @@ # defaults file for test_mysql_user mysql_user: root mysql_password: msandbox -mysql_host: 127.0.0.1 +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 db_name: 'data' diff --git a/tests/integration/targets/test_mysql_user/meta/main.yml b/tests/integration/targets/test_mysql_user/meta/main.yml index a7ace5d..4be5f58 100644 --- a/tests/integration/targets/test_mysql_user/meta/main.yml +++ b/tests/integration/targets/test_mysql_user/meta/main.yml @@ -1,3 +1,4 @@ +--- dependencies: - - setup_mysql + - setup_controller - setup_remote_tmp_dir diff --git a/tests/integration/targets/test_mysql_user/tasks/assert_no_user.yml b/tests/integration/targets/test_mysql_user/tasks/assert_no_user.yml deleted file mode 100644 index 9861084..0000000 --- a/tests/integration/targets/test_mysql_user/tasks/assert_no_user.yml +++ /dev/null @@ -1,25 +0,0 @@ -# test code to assert no mysql user -# (c) 2014, Wayne Rosario - -# 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 . - -# ============================================================ -- name: run command to query for mysql user - command: "{{ mysql_command }} -e \"SELECT User FROM mysql.user where user='{{ user_name }}'\"" - register: result - -- name: assert mysql user is not present - assert: { that: "'{{ user_name }}' not in result.stdout" } diff --git a/tests/integration/targets/test_mysql_user/tasks/assert_user.yml b/tests/integration/targets/test_mysql_user/tasks/assert_user.yml deleted file mode 100644 index d95d9d2..0000000 --- a/tests/integration/targets/test_mysql_user/tasks/assert_user.yml +++ /dev/null @@ -1,38 +0,0 @@ -# test code to assert mysql user -# (c) 2014, Wayne Rosario - -# 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 . - -# ============================================================ -- name: run command to query for mysql user - command: "{{ mysql_command }} -e \"SELECT User FROM mysql.user where user='{{ user_name }}'\"" - register: result - -- name: assert mysql user is present - assert: - that: - - "'{{ user_name }}' in result.stdout" - -- name: run command to show privileges for user (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name }}'@'localhost'\"" - register: result - when: priv is defined - -- name: assert user has giving privileges - assert: - that: - - "'GRANT {{priv}} ON *.*' in result.stdout" - when: priv is defined diff --git a/tests/integration/targets/test_mysql_user/tasks/create_user.yml b/tests/integration/targets/test_mysql_user/tasks/create_user.yml index 9c3459a..e69de29 100644 --- a/tests/integration/targets/test_mysql_user/tasks/create_user.yml +++ b/tests/integration/targets/test_mysql_user/tasks/create_user.yml @@ -1,40 +0,0 @@ -# test code to create mysql user -# (c) 2014, Wayne Rosario - -# 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 . - -- vars: - mysql_parameters: &mysql_params - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - - block: - - # ============================================================ - - name: create mysql user {{user_name}} - mysql_user: - <<: *mysql_params - name: '{{ user_name }}' - password: '{{ user_password }}' - state: present - register: result - - - name: assert output message mysql user was created - assert: - that: - - result is changed diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-121.yml b/tests/integration/targets/test_mysql_user/tasks/issue-121.yml index 29241d5..4209c0a 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-121.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-121.yml @@ -1,112 +1,85 @@ --- + - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - # ============================================================ - - - name: get server certificate + - name: Issue-121 | Setup | Get server certificate copy: - content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect localhost:3307 -showcerts 2>/dev/null /dev/null - + # Issue-121 | Create user with both REQUIRESSL privilege and an incompatible + # tls_requires option + # mysql_user: + # <<: *mysql_params + # name: "{{ user_name_1 }}" + # host: '{{ gateway_addr }}' + # password: "{{ user_password_1 }}" + # priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT' + # tls_requires: + # X509: - - name: create user with equivalent ssl requirement in tls_requires (expect unchanged) - mysql_user: - <<: *mysql_params - name: "{{ user_name_1 }}" - password: "{{ user_password_1 }}" - priv: '*.*:SELECT,CREATE USER,GRANT' - tls_requires: - SSL: - register: result + # - name: Issue-121 | Create same user again without REQUIRESSL privilege + # mysql_user: + # <<: *mysql_params + # name: "{{ user_name_1 }}" + # password: "{{ user_password_1 }}" + # priv: '*.*:SELECT,CREATE USER,GRANT' + # tls_requires: + # X509: + # register: result + # ignore_errors: true - - assert: - that: - - result is not changed + # - name: >- + # Issue-121 | Assert error granting privileges with incompatible tls_requires + # option + # assert: + # that: + # - result is not changed - - name: create the same user again, with REQUIRESSL privilege once more - mysql_user: - <<: *mysql_params - name: "{{ user_name_1 }}" - password: "{{ user_password_1 }}" - priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT' - register: result - - - assert: - that: - - result is not changed - - - name: create user with both REQUIRESSL privilege and an incompatible tls_requires option - mysql_user: - <<: *mysql_params - name: "{{ user_name_1 }}" - password: "{{ user_password_1 }}" - priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT' - tls_requires: - X509: - - - name: create same user again without REQUIRESSL privilege - mysql_user: - <<: *mysql_params - name: "{{ user_name_1 }}" - password: "{{ user_password_1 }}" - priv: '*.*:SELECT,CREATE USER,GRANT' - tls_requires: - X509: - register: result - - - assert: - that: result is not changed - - - name: Drop mysql user + - name: Issue-121 | Teardown | Drop mysql user mysql_user: <<: *mysql_params name: '{{ item }}' - host: 127.0.0.1 + host_all: true state: absent with_items: - "{{ user_name_1 }}" diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-265.yml b/tests/integration/targets/test_mysql_user/tasks/issue-265.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml index 437ce81..51a2091 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml @@ -9,81 +9,87 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: # ============================================================ - - - name: get server certificate + - name: Issue-28 | Setup | Get server certificate copy: - content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect localhost:3307 -showcerts 2>/dev/null /dev/null = 0.7.11 is required' in result.msg - - name: Drop mysql user + - name: Issue-28 | Drop mysql user mysql_user: <<: *mysql_params name: '{{ item }}' - host: 127.0.0.1 + host: '{{ gateway_addr }}' state: absent with_items: - "{{ user_name_1 }}" diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-29511.yaml b/tests/integration/targets/test_mysql_user/tasks/issue-29511.yaml index 31e6edf..17eb200 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-29511.yaml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-29511.yaml @@ -3,12 +3,12 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: Issue test setup - drop database + - name: Issue-29511 | test setup | drop database mysql_db: <<: *mysql_params name: "{{ item }}" @@ -17,7 +17,7 @@ - foo - bar - - name: Issue test setup - create database + - name: Issue-29511 | test setup | create database mysql_db: <<: *mysql_params name: "{{ item }}" @@ -26,7 +26,7 @@ - foo - bar - - name: Copy SQL scripts to remote + - name: Issue-29511 | Copy SQL scripts to remote copy: src: "{{ item }}" dest: "{{ remote_tmp_dir }}/{{ item | basename }}" @@ -34,13 +34,13 @@ - create-function.sql - create-procedure.sql - - name: Create function for test + - name: Issue-29511 | Create function for test shell: "{{ mysql_command }} < {{ remote_tmp_dir }}/create-function.sql" - - name: Create procedure for test + - name: Issue-29511 | Create procedure for test shell: "{{ mysql_command }} < {{ remote_tmp_dir }}/create-procedure.sql" - - name: Create user with FUNCTION and PROCEDURE privileges + - name: Issue-29511 | Create user with FUNCTION and PROCEDURE privileges mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -49,13 +49,13 @@ priv: 'FUNCTION foo.function:EXECUTE/foo.*:SELECT/PROCEDURE bar.procedure:EXECUTE' register: result - - name: Assert Create user with FUNCTION and PROCEDURE privileges + - name: Issue-29511 | Assert Create user with FUNCTION and PROCEDURE privileges assert: that: - result is success - result is changed - - name: Create user with FUNCTION and PROCEDURE privileges - Idempotent check + - name: Issue-29511 | Create user with FUNCTION and PROCEDURE privileges - Idempotent check mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -64,19 +64,13 @@ priv: 'FUNCTION foo.function:EXECUTE/foo.*:SELECT/PROCEDURE bar.procedure:EXECUTE' register: result - - name: Assert Create user with FUNCTION and PROCEDURE privileges + - name: Issue-29511 | Assert Create user with FUNCTION and PROCEDURE privileges assert: that: - result is success - result is not changed - - name: Remove user - mysql_user: - <<: *mysql_params - name: '{{ user_name_2 }}' - state: absent - - - name: Issue test teardown - cleanup databases + - name: Issue-29511 | Test teardown | cleanup databases mysql_db: <<: *mysql_params name: "{{ item }}" @@ -84,3 +78,5 @@ loop: - foo - bar + + - include: utils/remove_user.yml user_name="{{ user_name_2 }}" diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml b/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml index 1c0af68..a7657f8 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-64560.yaml @@ -3,47 +3,50 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: Set root password + - name: Issue-64560 | Set root password mysql_user: <<: *mysql_params name: root + host: '%' password: '{{ root_password }}' check_implicit_admin: yes register: result - - name: assert root password is changed + - name: Issue-64560 | Assert root password is changed assert: that: - result is changed - - name: Set root password again + - name: Issue-64560 | Set root password again mysql_user: login_user: '{{ mysql_user }}' login_password: '{{ root_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: root + host: '%' password: '{{ root_password }}' check_implicit_admin: yes register: result - - name: Assert root password is not changed + - name: Issue-64560 | Assert root password is not changed assert: that: - result is not changed - - name: Set root password again + - name: Issue-64560 | Set root password again mysql_user: login_user: '{{ mysql_user }}' login_password: '{{ root_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' name: root + host: '%' password: '{{ mysql_password }}' check_implicit_admin: yes register: result diff --git a/tests/integration/targets/test_mysql_user/tasks/main.yml b/tests/integration/targets/test_mysql_user/tasks/main.yml index 5ddf300..2569d4a 100644 --- a/tests/integration/targets/test_mysql_user/tasks/main.yml +++ b/tests/integration/targets/test_mysql_user/tasks/main.yml @@ -1,3 +1,4 @@ +--- #################################################################### # WARNING: These are designed specifically for Ansible tests # # and should not be used as examples of how to write Ansible roles # @@ -24,15 +25,12 @@ # ============================================================ # create mysql user and verify user is added to mysql database # -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: @@ -41,109 +39,49 @@ - include: issue-28.yml - - include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + - include: test_resource_limits.yml - - include: resource_limits.yml - - - include: assert_user.yml user_name={{user_name_1}} - - - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - - - include: assert_no_user.yml user_name={{user_name_1}} - - # ============================================================ - # Create mysql user that already exist on mysql database - # - - include: create_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} - - - name: create mysql user that already exist (expect changed=false) - mysql_user: - <<: *mysql_params - name: '{{user_name_1}}' - password: '{{user_password_1}}' - state: present - register: result - - - name: assert output message mysql user was not created - assert: - that: - - result is not changed - - # ============================================================ - # remove mysql user and verify user is removed from mysql database - # - - name: remove mysql user state=absent (expect changed=true) - mysql_user: - <<: *mysql_params - name: '{{ user_name_1 }}' - password: '{{ user_password_1 }}' - state: absent - register: result - - - name: assert output message mysql user was removed - assert: - that: - - result is changed - - - include: assert_no_user.yml user_name={{user_name_1}} - - # ============================================================ - # remove mysql user that does not exist on mysql database - # - - name: remove mysql user that does not exist state=absent (expect changed=false) - mysql_user: - <<: *mysql_params - name: '{{ user_name_1 }}' - password: '{{ user_password_1 }}' - state: absent - register: result - - - name: assert output message mysql user that does not exist - assert: - that: - - result is not changed - - - include: assert_no_user.yml user_name={{user_name_1}} + - include: test_idempotency.yml # ============================================================ # Create user with no privileges and verify default privileges are assign # - - name: create user with select privilege state=present (expect changed=true) + - name: create user with DEFAULT privilege state=present (expect changed=true) mysql_user: <<: *mysql_params - name: '{{ user_name_1 }}' - password: '{{ user_password_1 }}' + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" state: present register: result - - include: assert_user.yml user_name={{user_name_1}} priv=USAGE + - include: utils/assert_user.yml user_name={{ user_name_1 }} user_host=localhost priv=USAGE - - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{ user_name_1 }} - - include: assert_no_user.yml user_name={{user_name_1}} + - include: utils/assert_no_user.yml user_name={{ user_name_1 }} # ============================================================ # Create user with select privileges and verify select privileges are assign # - - name: create user with select privilege state=present (expect changed=true) + - name: Create user with SELECT privilege state=present (expect changed=true) mysql_user: <<: *mysql_params - name: '{{ user_name_2 }}' - password: '{{ user_password_2 }}' + name: "{{ user_name_2 }}" + password: "{{ user_password_2 }}" state: present priv: '*.*:SELECT' register: result - - include: assert_user.yml user_name={{user_name_2}} priv=SELECT + - include: utils/assert_user.yml user_name={{ user_name_2 }} user_host=localhost priv=SELECT - - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_2 }} + - include: utils/remove_user.yml user_name={{ user_name_2 }} - - include: assert_no_user.yml user_name={{user_name_2}} + - include: utils/assert_no_user.yml user_name={{ user_name_2 }} # ============================================================ # Assert user has access to multiple databases # - - name: give users access to multiple databases + - name: Give users access to multiple databases mysql_user: <<: *mysql_params name: '{{ item[0] }}' @@ -151,34 +89,34 @@ append_privs: yes password: '{{ user_password_1 }}' with_nested: - - [ '{{ user_name_1 }}', '{{ user_name_2 }}'] + - ['{{ user_name_1 }}', '{{ user_name_2 }}'] - "{{db_names}}" - - name: show grants access for user1 on multiple database + - name: Show grants access for user1 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result - - name: assert grant access for user1 on multiple database + - name: Assert grant access for user1 on multiple database assert: that: - "'{{ item }}' in result.stdout" - with_items: "{{db_names}}" + with_items: "{{ db_names }}" - - name: show grants access for user2 on multiple database + - name: Show grants access for user2 on multiple database command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_2 }}'@'localhost'\"" register: result - - name: assert grant access for user2 on multiple database + - name: Assert grant access for user2 on multiple database assert: that: - "'{{ item }}' in result.stdout" with_items: "{{db_names}}" - - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{ user_name_1 }} - - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{ user_name_2 }} - - name: give user access to database via wildcard + - name: Give user SELECT access to database via wildcard mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -186,7 +124,7 @@ append_privs: yes password: '{{ user_password_1 }}' - - name: show grants access for user1 on multiple database + - name: Show grants access for user1 on database via wildcard command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result @@ -201,8 +139,8 @@ <<: *mysql_params name: '{{ user_name_1 }}' priv: - - unsuitable - - type + - unsuitable + - type append_privs: yes host_all: yes password: '{{ user_password_1 }}' @@ -215,7 +153,7 @@ - result is failed - result.msg is search('priv parameter must be str or dict') - - name: change user access to database via wildcard + - name: Change SELECT to INSERT for user access to database via wildcard mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -224,7 +162,7 @@ host_all: yes password: '{{ user_password_1 }}' - - name: show grants access for user1 on multiple database + - name: Show grants access for user1 on database via wildcard command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_1 }}'@'localhost'\"" register: result @@ -234,7 +172,7 @@ - "'%db' in result.stdout" - "'INSERT' in result.stdout" - - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{user_name_1}} # ============================================================ # Test plaintext and encrypted password scenarios. @@ -246,7 +184,7 @@ # # FIXME: mariadb sql syntax for create/update user is not compatible - include: test_user_plugin_auth.yml - when: install_type == 'mysql' + when: db_engine == 'mysql' # ============================================================ # Assert create user with SELECT privileges, attempt to create database and update privileges to create database @@ -277,7 +215,7 @@ - include: test_priv_append.yml enable_check_mode=yes # Tests for the TLS requires dictionary - - include: tls_requirements.yml + - include: test_tls_requirements.yml - import_tasks: issue-29511.yaml tags: @@ -289,3 +227,5 @@ # https://github.com/ansible-collections/community.mysql/issues/231 - include: test_user_grants_with_roles_applied.yml + + - include: test_revoke_only_grant.yml diff --git a/tests/integration/targets/test_mysql_user/tasks/remove_user.yml b/tests/integration/targets/test_mysql_user/tasks/remove_user.yml deleted file mode 100644 index 7a2c9e9..0000000 --- a/tests/integration/targets/test_mysql_user/tasks/remove_user.yml +++ /dev/null @@ -1,74 +0,0 @@ -# test code to remove mysql user -# (c) 2014, Wayne Rosario - -# 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 . - -- vars: - mysql_parameters: &mysql_params - login_user: '{{ mysql_user }}' - login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 - login_port: '{{ mysql_primary_port }}' - - block: - - # ============================================================ - - name: remove mysql user {{user_name}} - mysql_user: - <<: *mysql_params - name: '{{user_name}}' - password: '{{user_password}}' - state: absent - register: result - - - name: assert output message mysql user was removed - assert: - that: - - result is changed - - # ============================================================ - - name: create blank mysql user to be removed later - mysql_user: - <<: *mysql_params - name: "" - state: present - password: 'KJFDY&D*Sfuydsgf' - - - name: remove blank mysql user with hosts=all (expect changed) - mysql_user: - <<: *mysql_params - user: "" - host_all: true - state: absent - register: result - - - name: assert changed is true for removing all blank users - assert: - that: - - result is changed - - - name: remove blank mysql user with hosts=all (expect ok) - mysql_user: - <<: *mysql_params - user: "" - host_all: true - state: absent - register: result - - - name: assert changed is true for removing all blank users - assert: - that: - - result is not changed diff --git a/tests/integration/targets/test_mysql_user/tasks/test_idempotency.yml b/tests/integration/targets/test_mysql_user/tasks/test_idempotency.yml new file mode 100644 index 0000000..cc6850c --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_idempotency.yml @@ -0,0 +1,84 @@ +--- +- vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + + block: + # ======================================================================== + # Creation + # ======================================================================== + - include: utils/create_user.yml user_name={{ user_name_1 }} user_password={{ user_password_1 }} + + - name: Idempotency | Create user that already exist (expect changed=false) + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" + state: present + register: result + + - name: Idempotency | Assert create user task is not changed + assert: {that: [result is not changed]} + + # ======================================================================== + # Removal + # ======================================================================== + - name: Idempotency | Remove user (expect changed=true) + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + state: absent + register: result + + - name: Idempotency | Assert remove user task is changed + ansible.builtin.assert: + that: + - result is changed + + - name: Idempotency | Remove user that doesn't exists (expect changed=false) + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + state: absent + register: result + + - name: Idempotency | Assert remove user task is not changed + ansible.builtin.assert: + that: + - result is not changed + + # ======================================================================== + # Removal with host_all + # ======================================================================== + + # Create blank user to be removed later + - include: utils/create_user.yml user_name="" user_password='KJFDY&D*Sfuysf' + + - name: Idempotency | Remove blank user with hosts=all (expect changed) + mysql_user: + <<: *mysql_params + user: "" + host_all: true + state: absent + register: result + + - name: Idempotency | Assert removing all blank users is changed + ansible.builtin.assert: + that: + - result is changed + + - name: Idempotency | Remove blank user with hosts=all (expect ok) + mysql_user: + <<: *mysql_params + user: "" + host_all: true + state: absent + register: result + + - name: Idempotency | Assert removing all blank users is not changed + ansible.builtin.assert: + that: + - result is not changed diff --git a/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml b/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml index 72e933b..3fa317f 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_priv_append.yml @@ -1,45 +1,48 @@ +--- # Test code to ensure that appending privileges will not result in unnecessary changes when the current privileges # are a superset of the new privileges that have been defined. - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: Create test databases + - name: Priv append | Create test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 - - data2 + - data1 + - data2 - - name: Create a user with an initial set of privileges + - name: Priv append | Create a user with an initial set of privileges mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:SELECT,INSERT/data2.*:SELECT,DELETE' state: present - - name: Run command to show privileges for user (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" + - name: Priv append | Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'%'\"" register: result - - name: Assert that the initial set of privileges matches what is expected + - name: Priv append | Assert that the initial set of privileges matches what is expected assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" - - name: Append privileges that are a subset of the current privileges, which should be a no-op + - name: Priv append | Append privileges that are a subset of the current privileges, which should be a no-op mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:SELECT/data2.*:SELECT' append_privs: yes @@ -47,25 +50,26 @@ check_mode: '{{ enable_check_mode }}' register: result - - name: Assert that there wasn't a change in permissions + - name: Priv append | Assert that there wasn't a change in permissions assert: that: - result is not changed - - name: Run command to show privileges for user (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" + - name: Priv append | Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'%'\"" register: result - - name: Assert that the permissions still match what was originally granted + - name: Priv append | Assert that the permissions still match what was originally granted assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" - - name: Append privileges that are not included in the current set of privileges to test that privileges are updated + - name: Priv append | Append privileges that are not included in the current set of privileges to test that privileges are updated mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:DELETE/data2.*:SELECT' append_privs: yes @@ -73,29 +77,51 @@ check_mode: '{{ enable_check_mode }}' register: result - - name: Assert that there was a change because permissions were added to data1.* + - name: Priv append | Assert that there was a change because permissions were added to data1.* assert: that: - result is changed - - name: Run command to show privileges for user (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\"" + - name: Priv append | Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'%'\"" register: result - - name: Assert that the permissions were changed as expected if check_mode is set to 'no' + - name: Priv append | Assert that the permissions were changed as expected if check_mode is set to 'no' assert: that: - "'GRANT SELECT, INSERT, DELETE ON `data1`.*' in result.stdout" - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" when: enable_check_mode == 'no' - - name: Assert that the permissions were not actually changed if check_mode is set to 'yes' + - name: Priv append | Assert that the permissions were not actually changed if check_mode is set to 'yes' assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" - "'GRANT SELECT, DELETE ON `data2`.*' in result.stdout" when: enable_check_mode == 'yes' + - name: Priv append | Try to append invalid privileges + mysql_user: + <<: *mysql_params + name: '{{ user_name_4 }}' + host: '%' + password: '{{ user_password_4 }}' + priv: 'data1.*:INVALID/data2.*:SELECT' + append_privs: yes + state: present + check_mode: '{{ enable_check_mode }}' + register: result + ignore_errors: true + + - name: Priv append | Assert that there wasn't a change in privileges if check_mode is set to 'no' + assert: + that: + - result is failed + - > + 'Error granting privileges' in result.msg + or 'invalid privileges string' in result.msg + when: enable_check_mode == 'no' + ########## # Clean up - name: Drop test databases @@ -104,11 +130,7 @@ name: '{{ item }}' state: present loop: - - data1 - - data2 + - data1 + - data2 - - name: Drop test user - mysql_user: - <<: *mysql_params - name: '{{ user_name_4 }}' - state: absent + - include: utils/remove_user.yml user_name={{ user_name_4 }} diff --git a/tests/integration/targets/test_mysql_user/tasks/test_priv_dict.yml b/tests/integration/targets/test_mysql_user/tasks/test_priv_dict.yml index d54c946..82385e1 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_priv_dict.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_priv_dict.yml @@ -1,24 +1,25 @@ +--- - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: # Tests for priv parameter value passed as a dict - - name: Create test databases + - name: Priv dict | Create test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 - - data2 - - data3 + - data1 + - data2 + - data3 - - name: Create user with privileges + - name: Priv dict | Create user with privileges mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -28,7 +29,7 @@ "data2.*": "SELECT" state: present - - name: Run command to show privileges for user (expect privileges in stdout) + - name: Priv dict | Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" register: result @@ -39,12 +40,12 @@ - "'GRANT SELECT ON `data2`.*' in result.stdout" # Issue https://github.com/ansible-collections/community.mysql/issues/99 - - name: Create test table test_table_issue99 + - name: Priv dict | Create test table test_table_issue99 mysql_query: <<: *mysql_params query: "CREATE TABLE IF NOT EXISTS data3.test_table_issue99 (a INT, b INT, c INT)" - - name: Grant select on a column + - name: Priv dict | Grant select on a column mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -52,11 +53,12 @@ 'data3.test_table_issue99': 'SELECT (a)' register: result - - assert: + - name: Priv dict | Assert that select on a column is changed + assert: that: - - result is changed + - result is changed - - name: Grant select on the column again + - name: Priv dict | Grant select on the column again mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -64,12 +66,12 @@ 'data3.test_table_issue99': 'SELECT (a)' register: result - - assert: + - name: Priv dict | Assert that select on the column is not changed + assert: that: - - result is not changed + - result is not changed - - - name: Grant select on columns + - name: Priv dict | Grant select on columns mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -77,11 +79,12 @@ 'data3.test_table_issue99': 'SELECT (a, b),INSERT' register: result - - assert: + - name: Priv dict | Assert select on columns is changed + assert: that: - - result is changed + - result is changed - - name: Grant select on columns again + - name: Priv dict | Grant select on columns again mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -89,11 +92,12 @@ 'data3.test_table_issue99': 'SELECT (a, b),INSERT' register: result - - assert: + - name: Priv dict | Assert that select on columns again is not changed + assert: that: - - result is not changed + - result is not changed - - name: Grant privs on columns + - name: Priv dict | Grant privs on columns mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -101,11 +105,12 @@ 'data3.test_table_issue99': 'SELECT (a, b), INSERT (a, b), UPDATE' register: result - - assert: + - name: Priv dict | Assert that grant privs on columns is changed + assert: that: - - result is changed + - result is changed - - name: Grant same privs on columns again, note that the column order is different + - name: Priv dict | Grant same privs on columns again, note that the column order is different mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -113,21 +118,22 @@ 'data3.test_table_issue99': 'SELECT (a, b), UPDATE, INSERT (b, a)' register: result - - assert: + - name: Priv dict | Assert that grants same privs with different order is not changed + assert: that: - - result is not changed + - result is not changed - - name: Run command to show privileges for user (expect privileges in stdout) + - name: Priv dict | Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" register: result - - name: Assert user has giving privileges + - name: Priv dict | Assert user has giving privileges assert: that: - "'GRANT SELECT (`A`, `B`), INSERT (`A`, `B`), UPDATE' in result.stdout" when: "'(`A`, `B`)' in result.stdout" - - name: Assert user has giving privileges + - name: Priv dict | Assert user has giving privileges assert: that: - "'GRANT SELECT (A, B), INSERT (A, B), UPDATE' in result.stdout" @@ -135,18 +141,14 @@ ########## # Clean up - - name: Drop test databases + - name: Priv dict | Drop test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 - - data2 - - data3 + - data1 + - data2 + - data3 - - name: Drop test user - mysql_user: - <<: *mysql_params - name: '{{ user_name_3 }}' - state: absent + - include: utils/remove_user.yml user_name="{{ user_name_3 }}" diff --git a/tests/integration/targets/test_mysql_user/tasks/test_priv_subtract.yml b/tests/integration/targets/test_mysql_user/tasks/test_priv_subtract.yml new file mode 100644 index 0000000..e69de29 diff --git a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml index 17e42b3..55ac62d 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_privs.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml @@ -1,3 +1,4 @@ +--- # test code for privileges for mysql_user module # (c) 2014, Wayne Rosario @@ -20,56 +21,58 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: # ============================================================ - - name: create user with basic select privileges + - name: Privs | Create user with basic select privileges mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: '*.*:SELECT' state: present when: current_append_privs == "yes" - - include: assert_user.yml user_name={{user_name_2}} priv='SELECT' + - include: utils/assert_user.yml user_name={{ user_name_2 }} user_host=% priv='SELECT' when: current_append_privs == "yes" - - name: create user with current privileges (expect changed=true) + - name: Privs | Create user with current privileges (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' - priv: '*.*:{{current_privilege}}' - append_privs: '{{current_append_privs}}' + priv: '*.*:{{ current_privilege }}' + append_privs: '{{ current_append_privs }}' state: present register: result - - name: assert output message for current privileges + - name: Privs | Assert output message for current privileges assert: that: - result is changed - - name: run command to show privileges for user (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{user_name_2}}'@'localhost'\"" + - name: Privs | Run command to show privileges for user (expect privileges in stdout) + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{user_name_2}}'@'%'\"" register: result - - name: assert user has correct privileges + - name: Privs | Assert user has correct privileges assert: that: - - "'GRANT {{current_privilege | replace(',', ', ')}} ON *.*' in result.stdout" + - "'GRANT {{ current_privilege | replace(',', ', ') }} ON *.*' in result.stdout" when: current_append_privs == "no" - - name: assert user has correct privileges + - name: Privs | Assert user has correct privileges assert: that: - - "'GRANT SELECT, {{current_privilege | replace(',', ', ')}} ON *.*' in result.stdout" + - "'GRANT SELECT, {{ current_privilege | replace(',', ', ') }} ON *.*' in result.stdout" when: current_append_privs == "yes" - - name: create database using user current privileges + - name: Privs | Create database using user current privileges mysql_db: login_user: '{{ user_name_2 }}' login_password: '{{ user_password_2 }}' @@ -79,56 +82,59 @@ state: present ignore_errors: true - - name: run command to test that database was not created + - name: Privs | Run command to test that database was not created command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\"" register: result - - name: assert database was not created + - name: Privs | Assert database was not created assert: that: - - "'{{ db_name }}' not in result.stdout" + - db_name not in result.stdout # ============================================================ - - name: Add privs to a specific table (expect changed) + - name: Privs | Add privs to a specific table (expect changed) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: 'jmainguy.jmainguy:ALL' state: present register: result - - name: Assert that priv changed + - name: Privs | Assert that priv changed assert: that: - result is changed - - name: Add privs to a specific table (expect ok) + - name: Privs | Add privs to a specific table (expect ok) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: 'jmainguy.jmainguy:ALL' state: present register: result - - name: Assert that priv did not change + - name: Privs | Assert that priv did not change assert: that: - result is not changed # ============================================================ - - name: update user with all privileges + - name: Privs | Grant ALL to user {{ user_name_2 }} mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: '*.*:ALL' state: present - # - include: assert_user.yml user_name={{user_name_2}} priv='ALL PRIVILEGES' + # - include: utils/assert_user.yml user_name={{user_name_2}} user_host=% priv='ALL PRIVILEGES' - - name: create database using user + - name: Privs | Create database using user {{ user_name_2 }} mysql_db: login_user: '{{ user_name_2 }}' login_password: '{{ user_password_2 }}' @@ -137,10 +143,10 @@ name: '{{ db_name }}' state: present - - name: run command to test database was created using user new privileges + - name: Privs | Run command to test database was created using user new privileges command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE {{ db_name }}\"" - - name: drop database using user + - name: Privs | Drop database using user {{ user_name_2 }} mysql_db: login_user: '{{ user_name_2 }}' login_password: '{{ user_password_2 }}' @@ -150,37 +156,95 @@ state: absent # ============================================================ - - name: update user with a long privileges list (mysql has a special multiline grant output) + - name: Privs | Update user with a long privileges list (mysql has a special multiline grant output) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: '*.*:CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN,SUPER,CREATE,DROP,EVENT,LOCK TABLES,INSERT,UPDATE,DELETE,SELECT,SHOW VIEW,GRANT' state: present register: result - - name: Assert that priv changed + - name: Privs | Assert that priv changed assert: that: - result is changed - - name: Test idempotency (expect ok) + - name: Privs | Test idempotency with a long privileges list (expect ok) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' + host: '%' password: '{{ user_password_2 }}' priv: '*.*:CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN,SUPER,CREATE,DROP,EVENT,LOCK TABLES,INSERT,UPDATE,DELETE,SELECT,SHOW VIEW,GRANT' state: present register: result - - name: Assert that priv did not change + # FIXME: on mysql >=8 and mariadb >=10.5.2 there's always a change because + # the REPLICATION CLIENT privilege was renamed to BINLOG MONITOR + - name: Privs | Assert that priv did not change assert: that: - result is not changed - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.2', '==')) + + - include: utils/remove_user.yml user_name="{{ user_name_2 }}" # ============================================================ - - name: update user with invalid privileges + - name: Privs | Grant all privileges with grant option + mysql_user: + <<: *mysql_params + name: '{{ user_name_2 }}' + password: '{{ user_password_2 }}' + priv: '*.*:ALL,GRANT' + state: present + register: result + + - name: Privs | Assert that priv changed + assert: + that: + - result is changed + + - name: Privs | Collect user info by host + community.mysql.mysql_info: + <<: *mysql_params + filter: "users" + register: mysql_info_about_users + + - name: Privs | Assert that 'GRANT' permission is present + assert: + that: + - mysql_info_about_users.users.localhost.{{ user_name_2 }}.Grant_priv == 'Y' + + # Disabled on stable-1 because always returns changed. + # - name: Privs | Test idempotency (expect ok) + # mysql_user: + # <<: *mysql_params + # name: '{{ user_name_2 }}' + # password: '{{ user_password_2 }}' + # priv: '*.*:CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN,SUPER,CREATE,DROP,EVENT,LOCK TABLES,INSERT,UPDATE,DELETE,SELECT,SHOW VIEW,GRANT' + # state: present + # register: result + + # # FIXME: on mysql >=8 there's always a change (ALL PRIVILEGES -> specific privileges) + # - name: Privs | Assert that priv did not change + # assert: + # that: + # - result is not changed + + - name: Privs | Collect user info by host + community.mysql.mysql_info: + <<: *mysql_params + filter: "users" + register: mysql_info_about_users + + - name: Privs | Assert that 'GRANT' permission is present (by host) + assert: + that: + - mysql_info_about_users.users.localhost.{{ user_name_2 }}.Grant_priv == 'Y' + + # ============================================================ + - name: Privs | Update user with invalid privileges mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -190,14 +254,9 @@ register: result ignore_errors: yes - - name: Assert that priv did not change + - name: Privs | Assert that priv did not change assert: that: - result is failed - - name: remove username - mysql_user: - <<: *mysql_params - name: '{{ user_name_2 }}' - password: '{{ user_password_2 }}' - state: absent + - include: utils/remove_user.yml user_name="{{ user_name_2 }}" diff --git a/tests/integration/targets/test_mysql_user/tasks/test_privs_issue_465.yml b/tests/integration/targets/test_mysql_user/tasks/test_privs_issue_465.yml new file mode 100644 index 0000000..2e6a41e --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_privs_issue_465.yml @@ -0,0 +1,31 @@ +--- +# test code for privileges for mysql_user module - issue 465 + +- vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + + block: + + # ============================================================ + - name: Privs issue 465 | Create a user with parameters that will always cause an exception + mysql_user: + <<: *mysql_params + name: user_issue_465 + password: a_test_password_465 + priv: '*.{{ db_name }}:SELECT' + state: present + ignore_errors: true + register: result + + - name: Privs issue 465 | Assert output message for current privileges + assert: + that: + - result is failed + - result.msg is search('invalid priv string') + - result.msg is search('params') + - result.msg is search('query') + - result.msg is search('exception') diff --git a/tests/integration/targets/test_mysql_user/tasks/resource_limits.yml b/tests/integration/targets/test_mysql_user/tasks/test_resource_limits.yml similarity index 60% rename from tests/integration/targets/test_mysql_user/tasks/resource_limits.yml rename to tests/integration/targets/test_mysql_user/tasks/test_resource_limits.yml index 736adb3..7c2b97b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/resource_limits.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_resource_limits.yml @@ -1,20 +1,22 @@ +--- # test code for resource_limits parameter - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: Drop mysql user {{ user_name_1 }} if exists + - name: Resource limits | Drop mysql user {{ user_name_1 }} if exists mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent - - name: Create mysql user {{ user_name_1 }} with resource limits in check_mode + - name: Resource limits | Create mysql user {{ user_name_1 }} with resource limits in check_mode mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -26,11 +28,12 @@ check_mode: yes register: result - - assert: + - name: Resource limits | Assert that create user with resource limits is changed + assert: that: - result is changed - - name: Create mysql user {{ user_name_1 }} with resource limits in actual mode + - name: Resource limits | Create mysql user {{ user_name_1 }} with resource limits in actual mode mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -45,19 +48,23 @@ that: - result is changed - - name: Check + - name: Resource limits | Retrieve user mysql_query: <<: *mysql_params query: > - SELECT User FROM mysql.user WHERE User = '{{ user_name_1 }}' AND Host = 'localhost' - AND max_questions = 10 AND max_connections = 5 + SELECT User FROM mysql.user + WHERE User = '{{ user_name_1 }}' + AND Host = 'localhost' + AND max_questions = 10 + AND max_connections = 5 register: result - - assert: + - name: Resource limits | Assert that rowcount is 1 + assert: that: - - result.rowcount[0] == 1 + - result.rowcount[0] == 1 - - name: Try to set the same limits again in check mode + - name: Resource limits | Try to set the same limits again in check mode mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -69,11 +76,12 @@ check_mode: yes register: result - - assert: + - name: Resource limits | Assert that set same limits again is not changed + assert: that: - result is not changed - - name: Try to set the same limits again in actual mode + - name: Resource limits | Try to set the same limits again in actual mode mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -84,11 +92,12 @@ MAX_CONNECTIONS_PER_HOUR: 5 register: result - - assert: + - name: Resource limits | Assert that set same limits again in actual mode is not changed + assert: that: - result is not changed - - name: Change limits + - name: Resource limits | Change limits mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -99,19 +108,24 @@ MAX_CONNECTIONS_PER_HOUR: 5 register: result - - assert: + - name: Resource limits | Assert limits changed + assert: that: - result is changed - - name: Check + - name: Resource limits | Get user limits mysql_query: <<: *mysql_params query: > - SELECT User FROM mysql.user WHERE User = '{{ user_name_1 }}' AND Host = 'localhost' - AND max_questions = 5 AND max_connections = 5 + SELECT User FROM mysql.user + WHERE User = '{{ user_name_1 }}' + AND Host = 'localhost' + AND max_questions = 5 + AND max_connections = 5 register: result - - assert: + - name: Resource limits | Assert limit row count + assert: that: - result.rowcount[0] == 1 diff --git a/tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml b/tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml new file mode 100644 index 0000000..de0fc62 --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml @@ -0,0 +1,50 @@ +--- +- vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + block: + - include: utils/remove_user.yml user_name={{ user_name_1 }} + + - name: Revoke only grants | Create user with two grants + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" + update_password: on_create + priv: '*.*:SELECT,GRANT' + + - name: Revoke only grants | Revoke grant priv from db_user1 + register: result + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" + update_password: on_create + priv: '*.*:SELECT' + + - name: Revoke only grants | Assert that db_user1 only have one priv left + assert: + that: + - result is not failed + - result is changed + + - name: Revoke only grants | Update db_user1 again to test idempotence + register: result + mysql_user: + <<: *mysql_params + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" + update_password: on_create + priv: '*.*:SELECT' + + - name: Revoke only grants | Assert that task is idempotent + assert: + that: + - result is succeeded + - result is not changed + + always: + - include: utils/remove_user.yml user_name={{ user_name_1 }} diff --git a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml b/tests/integration/targets/test_mysql_user/tasks/test_tls_requirements.yml similarity index 57% rename from tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml rename to tests/integration/targets/test_mysql_user/tasks/test_tls_requirements.yml index 7bf142e..f85ae3b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/tls_requirements.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_tls_requirements.yml @@ -3,26 +3,12 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - # ============================================================ - - name: find out the database version - mysql_info: - <<: *mysql_params - filter: version - register: db_version - - - name: Drop mysql user {{ item }} if exists - mysql_user: - <<: *mysql_params - name: '{{ item }}' - state: absent - with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - - - name: create user with TLS requirements in check mode (expect changed=true) + - name: Tls reqs | Create user with TLS requirements in check mode (expect changed=true) mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" @@ -32,14 +18,14 @@ check_mode: yes register: result - - name: Assert check mode user create reports changed state + - name: Tls reqs | Assert check mode user create reports changed state assert: that: - result is changed - - include: assert_no_user.yml user_name={{user_name_1}} + - include: utils/assert_no_user.yml user_name={{user_name_1}} - - name: create user with TLS requirements state=present (expect changed=true) + - name: Tls reqs | Create user with TLS requirements state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ item[0] }}' @@ -55,45 +41,49 @@ issuer: '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' - block: - - name: retrieve TLS requirements for users in old database version + - name: Tls reqs | Retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ item }}'@'localhost'\"" register: old_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - - name: set old database separator + - name: Tls reqs | Set old database separator set_fact: separator: '\n' # Semantically: when mysql version <= 5.6 or MariaDB version <= 10.1 - when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 + when: + - (db_engine == 'mysql' and db_version is version('5.6', '<=')) + or (db_engine == 'mariadb' and db_version is version('10.1', '<=')) - block: - - name: retrieve TLS requirements for users in new database version + - name: Tls reqs | Retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ item }}'@'localhost'\"" register: new_result with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}'] - - name: set new database separator + - name: Tls reqs | Set new database separator set_fact: separator: 'PASSWORD' # Semantically: when mysql version >= 5.7 or MariaDB version >= 10.2 - when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 + when: + - (db_engine == 'mysql' and db_version is version('5.7', '>=')) + or (db_engine == 'mariadb' and db_version is version('10.2', '>=')) - block: - - name: assert user1 TLS requirements + - name: Tls reqs | Assert user1 TLS requirements assert: that: - "'SSL' in reqs" vars: - reqs: "{{((old_result.results[0] is skipped | ternary(new_result, old_result)).results | selectattr('item', 'contains', user_name_1) | first).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - - name: assert user2 TLS requirements + - name: Tls reqs | Assert user2 TLS requirements assert: that: - "'X509' in reqs" vars: - reqs: "{{((old_result.results[0] is skipped | ternary(new_result, old_result)).results | selectattr('item', 'contains', user_name_2) | first).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - - name: assert user3 TLS requirements + - name: Tls reqs | Assert user3 TLS requirements assert: that: - "'/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland' in (reqs | select('contains', 'SUBJECT') | first)" @@ -104,7 +94,7 @@ # CentOS 6 uses an older version of jinja that does not provide the selectattr filter. when: ansible_distribution != 'CentOS' or ansible_distribution_major_version != '6' - - name: modify user with TLS requirements state=present in check mode (expect changed=true) + - name: Tls reqs | Modify user with TLS requirements state=present in check mode (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -114,28 +104,32 @@ check_mode: yes register: result - - name: Assert check mode user update reports changed state + - name: Tls reqs | Assert check mode user update reports changed state assert: that: - result is changed - - name: retrieve TLS requirements for users in old database version + - name: Tls reqs | Retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" register: old_result - when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 + when: + - (db_engine == 'mysql' and db_version is version('5.6', '<=')) + or (db_engine == 'mariadb' and db_version is version('10.2', '<')) - - name: retrieve TLS requirements for users in new database version + - name: Tls reqs | Retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: new_result - when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 + when: + - (db_engine == 'mysql' and db_version is version('5.7', '>=')) + or (db_engine == 'mariadb' and db_version is version('10.2', '>=')) - - name: assert user1 TLS requirements was not changed + - name: Tls reqs | Assert user1 TLS requirements was not changed assert: that: "'SSL' in reqs" vars: - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - - name: modify user with TLS requirements state=present (expect changed=true) + - name: Tls reqs | Modify user with TLS requirements state=present (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' @@ -143,45 +137,49 @@ tls_requires: X509: - - name: retrieve TLS requirements for users in old database version + - name: Tls reqs | Retrieve TLS requirements for users in old database version command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\"" register: old_result - when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 + when: + - (db_engine == 'mysql' and db_version is version('5.6', '<=')) + or (db_engine == 'mariadb' and db_version is version('10.2', '<')) - - name: retrieve TLS requirements for users in new database version + - name: Tls reqs | Retrieve TLS requirements for users in new database version command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: new_result - when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2 + when: + - (db_engine == 'mysql' and db_version is version('5.7', '>=')) + or (db_engine == 'mariadb' and db_version is version('10.2', '>=')) - - name: assert user1 TLS requirements + - name: Tls reqs | Assert user1 TLS requirements assert: that: "'X509' in reqs" vars: - reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}" - - name: remove TLS requirements from user (expect changed=true) + - name: Tls reqs | Remove TLS requirements from user (expect changed=true) mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' password: '{{ user_password_1 }}' tls_requires: - - name: retrieve TLS requirements for users + - name: Tls reqs | Retrieve TLS requirements for users command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\"" register: result - - name: assert user1 TLS requirements + - name: Tls reqs | Assert user1 TLS requirements assert: that: "'REQUIRE ' not in result.stdout or 'REQUIRE NONE' in result.stdout" - - include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{user_name_1}} - - include: remove_user.yml user_name={{user_name_2}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{user_name_2}} - - include: remove_user.yml user_name={{user_name_3}} user_password={{ user_password_1 }} + - include: utils/remove_user.yml user_name={{user_name_3}} - - include: assert_no_user.yml user_name={{user_name_1}} + - include: utils/assert_no_user.yml user_name={{user_name_1}} - - include: assert_no_user.yml user_name={{user_name_2}} + - include: utils/assert_no_user.yml user_name={{user_name_2}} - - include: assert_no_user.yml user_name={{user_name_3}} + - include: utils/assert_no_user.yml user_name={{user_name_3}} diff --git a/tests/integration/targets/test_mysql_user/tasks/test_update_password.yml b/tests/integration/targets/test_mysql_user/tasks/test_update_password.yml new file mode 100644 index 0000000..428c1ef --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/test_update_password.yml @@ -0,0 +1,129 @@ +--- +# Tests scenarios for both plaintext and encrypted user passwords. + +- vars: + mysql_parameters: + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + test_password1: kbB9tcx5WOGVGfzV + test_password1_hash: '*AF6A7F9D038475C17EE46564F154104877EE5037' + test_password2: XBYjpHmjIctMxl1y + test_password2_hash: '*9E22D1B35C68BDDF398B8F28AE482E5A865BAC0A' + test_password3: tem33JfR5Yx98BB + test_password3_hash: '*C7E7C2710702F20336F8D93BC0670C8FB66BDBC7' + + + block: + - include_tasks: utils/assert_user_password.yml + vars: + username: "{{ item.username }}" + host: "%" + update_password: "{{ item.update_password }}" + password: "{{ test_password1 }}" + expect_change: "{{ item.expect_change }}" + expect_password_change: "{{ item.expect_change }}" + expect_password_hash: "{{ test_password1_hash }}" + loop: + # all variants set the password when nothing exists + - username: test1 + update_password: always + expect_change: true + - username: test2 + update_password: on_create + expect_change: true + - username: test3 + update_password: on_new_username + expect_change: true + + # assert idempotency + - username: test1 + update_password: always + expect_change: false + - username: test2 + update_password: on_create + expect_change: false + - username: test3 + update_password: on_new_username + expect_change: false + + # same user, new password + - include_tasks: utils/assert_user_password.yml + vars: + username: "{{ item.username }}" + host: "%" + update_password: "{{ item.update_password }}" + password: "{{ test_password2 }}" + expect_change: "{{ item.expect_change }}" + expect_password_change: "{{ item.expect_change }}" + expect_password_hash: "{{ item.expect_password_hash }}" + loop: + - username: test1 + update_password: always + expect_change: true + expect_password_hash: "{{ test_password2_hash }}" + - username: test2 + update_password: on_create + expect_change: false + expect_password_hash: "{{ test_password1_hash }}" + - username: test3 + update_password: on_new_username + expect_change: false + expect_password_hash: "{{ test_password1_hash }}" + + # new user, new password + - include_tasks: utils/assert_user_password.yml + vars: + username: "{{ item.username }}" + host: '::1' + update_password: "{{ item.update_password }}" + password: "{{ item.password }}" + expect_change: "{{ item.expect_change }}" + expect_password_change: "{{ item.expect_password_change }}" + expect_password_hash: "{{ item.expect_password_hash }}" + loop: + - username: test1 + update_password: always + expect_change: true + expect_password_change: true + password: "{{ test_password1 }}" + expect_password_hash: "{{ test_password1_hash }}" + - username: test2 + update_password: on_create + expect_change: true + expect_password_change: true + password: "{{ test_password2 }}" + expect_password_hash: "{{ test_password2_hash }}" + - username: test3 + update_password: on_new_username + expect_change: true + expect_password_change: false + password: "{{ test_password2 }}" + expect_password_hash: "{{ test_password1_hash }}" + + # prepare for next test: ensure all users have varying passwords + - username: test3 + update_password: always + expect_change: true + expect_password_change: true + password: "{{ test_password2 }}" + expect_password_hash: "{{ test_password2_hash }}" + + # another new user, another new password and multiple existing users with varying passwords + - include_tasks: utils/assert_user_password.yml + vars: + username: "{{ item.username }}" + host: '2001:db8::1' + update_password: "{{ item.update_password }}" + password: "{{ test_password3 }}" + expect_change: true + expect_password_change: true + expect_password_hash: "{{ test_password3_hash }}" + loop: + - username: test1 + update_password: always + - username: test2 + update_password: on_create + - username: test3 + update_password: on_new_username diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml index 7af3890..bd6c4e5 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_grants_with_roles_applied.yml @@ -1,31 +1,30 @@ +--- # https://github.com/ansible-collections/community.mysql/issues/231 - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: Get server version - mysql_info: - <<: *mysql_params - register: srv - # Skip unsupported versions - - meta: end_play - when: srv['version']['major'] < 8 + - name: User grants with roles applied | Skip unsupported versions + meta: end_play + when: + - db_engine == 'mysql' + - db_version is version('8.0.0', '<') - - name: Create test databases + - name: User grants with roles applied | Create test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 - - data2 + - data1 + - data2 - - name: Create user with privileges + - name: User grants with roles applied | Create user with privileges mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -35,7 +34,7 @@ "data2.*": "SELECT" state: present - - name: Run command to show privileges for user (expect privileges in stdout) + - name: User grants with roles applied | Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" register: result @@ -56,7 +55,7 @@ <<: *mysql_params query: 'GRANT test231 TO {{ user_name_3 }}@localhost' - - name: Try to change privs + - name: User grants with roles applied | Try to change privs mysql_user: <<: *mysql_params name: '{{ user_name_3 }}' @@ -65,11 +64,11 @@ "data2.*": "INSERT" state: present - - name: Run command to show privileges for user (expect privileges in stdout) + - name: User grants with roles applied | Run command to show privileges for user (expect privileges in stdout) command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\"" register: result - - name: Assert user has giving privileges + - name: User grants with roles applied | Assert user has giving privileges assert: that: - "'GRANT INSERT ON `data1`.*' in result.stdout" @@ -77,20 +76,16 @@ ########## # Clean up - - name: Drop test databases + - name: User grants with roles applied | Drop test databases mysql_db: <<: *mysql_params name: '{{ item }}' - state: present - loop: - - data1 - - data2 - - - name: Drop test user - mysql_user: - <<: *mysql_params - name: '{{ user_name_3 }}' state: absent + loop: + - data1 + - data2 + + - include: utils/remove_user.yml user_name={{ user_name_3 }} - name: Drop test role mysql_query: diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml index 57d8d29..d98c92c 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_password.yml @@ -1,10 +1,11 @@ +--- # Tests scenarios for both plaintext and encrypted user passwords. - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' test_user_name: 'test_user_password' initial_password: 'a5C8SN*DBa0%a75sGz' @@ -20,23 +21,24 @@ # Test setting plaintext password and changing it. # - - name: Create user with initial password + - name: Password | Create user with initial password mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' password: '{{ initial_password }}' priv: '{{ test_default_priv }}' state: present register: result - - name: Assert that a change occurred because the user was added + - name: Password | Assert that a change occurred because the user was added assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version using the newly created used creds + - name: Password | Get the MySQL version using the newly created used creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ initial_password }}' @@ -46,43 +48,45 @@ register: result ignore_errors: true - - name: Assert that mysql_info was successful + - name: Password | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Run mysql_user again without any changes + - name: Password | Run mysql_user again without any changes mysql_user: <<: *mysql_params - name: '{{ test_user_name }}' - password: '{{ initial_password }}' - priv: '{{ test_default_priv }}' + name: "{{ test_user_name }}" + host: "%" + password: "{{ initial_password }}" + priv: "{{ test_default_priv }}" state: present register: result - - name: Assert that there weren't any changes because username/password didn't change + - name: Password | Assert that there weren't any changes because username/password didn't change assert: that: - result is not changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Update the user password + - name: Password | Update the user password mysql_user: <<: *mysql_params - name: '{{ test_user_name }}' - password: '{{ new_password }}' + name: "{{ test_user_name }}" + host: "%" + password: "{{ new_password }}" state: present register: result - - name: Assert that a change occurred because the password was updated + - name: Password | Assert that a change occurred because the password was updated assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version data using the original password (should fail) + - name: Password | Get the MySQL version data using the original password (should fail) mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ initial_password }}' @@ -92,12 +96,12 @@ register: result ignore_errors: true - - name: Assert that the mysql_info module failed because we used the old password + - name: Password | Assert that the mysql_info module failed because we used the old password assert: that: - result is failed - - name: Get the MySQL version data using the new password (should work) + - name: Password | Get the MySQL version data using the new password (should work) mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ new_password }}' @@ -107,19 +111,19 @@ register: result ignore_errors: true - - name: Assert that the mysql_info module succeeded because we used the new password + - name: Password | Assert that the mysql_info module succeeded because we used the new password assert: that: - result is succeeded # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test setting a plaintext password and then the same password encrypted to ensure there isn't a change detected. # - - name: Create user with initial password + - name: Password | Create user with initial password mysql_user: <<: *mysql_params name: '{{ test_user_name }}' @@ -128,14 +132,14 @@ state: present register: result - - name: Assert that a change occurred because the user was added + - name: Password | Assert that a change occurred because the user was added assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }} - - name: Pass in the same password as before, but in the encrypted form (no change expected) + - name: Password | Pass in the same password as before, but in the encrypted form (no change expected) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' @@ -145,36 +149,37 @@ state: present register: result - - name: Assert that there weren't any changes because username/password didn't change + - name: Password | Assert that there weren't any changes because username/password didn't change assert: that: - result is not changed # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test setting an encrypted password and then the same password in plaintext to ensure there isn't a change. # - - name: Create user with initial password + - name: Password | Create user with initial password mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: "%" password: '{{ initial_password_encrypted }}' encrypted: yes priv: '{{ test_default_priv }}' state: present register: result - - name: Assert that a change occurred because the user was added + - name: Password | Assert that a change occurred because the user was added assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version data using the new creds + - name: Password | Get the MySQL version data using the new creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ initial_password }}' @@ -184,60 +189,62 @@ register: result ignore_errors: true - - name: Assert that the mysql_info module succeeded because we used the new password + - name: Password | Assert that the mysql_info module succeeded because we used the new password assert: that: - result is succeeded - - name: Pass in the same password as before, but in the encrypted form (no change expected) + - name: Password | Pass in the same password as before, but in the encrypted form (no change expected) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: "%" password: '{{ initial_password }}' state: present register: result - - name: Assert that there weren't any changes because username/password didn't change + - name: Password | Assert that there weren't any changes because username/password didn't change assert: that: - result is not changed # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test setting an empty password. # - - name: Create user with empty password + - name: Password | Create user with empty password mysql_user: <<: *mysql_params - name: '{{ test_user_name }}' - priv: '{{ test_default_priv }}' + name: "{{ test_user_name }}" + host: "%" + priv: "{{ test_default_priv }}" state: present register: result - - name: Assert that a change occurred because the user was added + - name: Password | Assert that a change occurred because the user was added assert: that: - result is changed - - name: Get the MySQL version using an empty password for the newly created user + - name: Password | Get the MySQL version using an empty password for the newly created user mysql_info: - login_user: '{{ test_user_name }}' - login_password: '' - login_host: '{{ mysql_host }}' - login_port: '{{ mysql_primary_port }}' + login_user: "{{ test_user_name }}" + login_password: "" + login_host: "{{ mysql_host }}" + login_port: "{{ mysql_primary_port }}" filter: version register: result ignore_errors: true - - name: Assert that mysql_info was successful + - name: Password | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Get the MySQL version using an non-empty password (should fail) + - name: Password | Get the MySQL version using an non-empty password (should fail) mysql_info: login_user: '{{ test_user_name }}' login_password: 'some_password' @@ -247,23 +254,24 @@ register: result ignore_errors: true - - name: Assert that mysql_info failed + - name: Password | Assert that mysql_info failed assert: that: - result is failed - - name: Update the user without changing the password + - name: Password | Update the user without changing the password mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: "%" priv: '{{ test_default_priv }}' state: present register: result - - name: Assert that the user wasn't changed because the password is still empty + - name: Password | Assert that the user wasn't changed because the password is still empty assert: that: - result is not changed # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password='' + - include: utils/remove_user.yml user_name={{ test_user_name }} diff --git a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml index 264d8bd..8d7740b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_user_plugin_auth.yml @@ -1,10 +1,11 @@ +--- # Test user plugin auth scenarios. - vars: mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' test_user_name: 'test_user_plugin_auth' test_plugin_type: 'mysql_native_password' @@ -21,33 +22,34 @@ # Test plugin auth initially setting a hash and then changing to a different hash. # - - name: Create user with plugin auth (with hash string) + - name: Plugin auth | Create user with plugin auth (with hash string) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_hash_string: '{{ test_plugin_hash }}' priv: '{{ test_default_priv }}' register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\"" + - name: Plugin auth | Get user information (with hash string) + command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = '%'\"" register: show_create_user - - name: Check that the module made a change + - name: Plugin auth | Check that the module made a change (with hash string) assert: that: - result is changed - - name: Check that the expected plugin type is set + - name: Plugin auth | Check that the expected plugin type is set (with hash string) assert: that: - "'{{ test_plugin_type }}' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version using the newly created creds + - name: Plugin auth | Get the MySQL version using the newly created creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_auth_string }}' @@ -56,27 +58,28 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Update the user with a different hash + - name: Plugin auth | Update the user with a different hash mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_hash_string: '{{ test_plugin_new_hash }}' register: result - - name: Check that the module makes the change because the hash changed + - name: Plugin auth | Check that the module makes the change because the hash changed assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Getting the MySQL info with the new password should work + - name: Plugin auth | Getting the MySQL info with the new password should work mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_new_auth_string }}' @@ -85,45 +88,46 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_new_auth_string }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test plugin auth initially setting a hash and then switching to a plaintext auth string. # - - name: Create user with plugin auth (with hash string) + - name: Plugin auth | Create user with plugin auth (with hash string) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_hash_string: '{{ test_plugin_hash }}' priv: '{{ test_default_priv }}' register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\"" + - name: Plugin auth | Get user information + command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = '%'\"" register: show_create_user - - name: Check that the module made a change + - name: Plugin auth | Check that the module made a change (with hash string) assert: that: - result is changed - - name: Check that the expected plugin type is set + - name: Plugin auth | Check that the expected plugin type is set (with hash string) assert: that: - "'{{ test_plugin_type }}' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version using the newly created creds + - name: Plugin auth | Get the MySQL version using the newly created creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_auth_string }}' @@ -132,43 +136,45 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Update the user with the same hash (no change expected) + - name: Plugin auth | Update the user with the same hash (no change expected) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_hash_string: '{{ test_plugin_hash }}' register: result # FIXME: on mariadb 10.2 there's always a change - - name: Check that the module doesn't make a change when the same hash is passed in + - name: Plugin auth | Check that the module doesn't make a change when the same hash is passed in assert: that: - result is not changed - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Change the user using the same plugin, but switch to the same auth string in plaintext form + - name: Plugin auth | Change the user using the same plugin, but switch to the same auth string in plaintext form mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_auth_string: '{{ test_plugin_auth_string }}' register: result # Expecting a change is currently by design (see comment in source). - - name: Check that the module did not change the password + - name: Plugin auth | Check that the module did not change the password assert: that: - result is changed - - name: Getting the MySQL info should still work + - name: Plugin auth | Getting the MySQL info should still work mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_auth_string }}' @@ -177,45 +183,46 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test plugin auth initially setting a plaintext auth string and then switching to a hash. # - - name: Create user with plugin auth (with auth string) + - name: Plugin auth | Create user with plugin auth (with auth string) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_auth_string: '{{ test_plugin_auth_string }}' priv: '{{ test_default_priv }}' register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + - name: Plugin auth | Get user information(with auth string) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'%'\"" register: show_create_user - - name: Check that the module made a change + - name: Plugin auth | Check that the module made a change (with auth string) assert: that: - result is changed - - name: Check that the expected plugin type is set + - name: Plugin auth | Check that the expected plugin type is set (with auth string) assert: that: - - "'{{ test_plugin_type }}' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + - test_plugin_type in show_create_user.stdout + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version using the newly created creds + - name: Plugin auth | Get the MySQL version using the newly created creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_auth_string }}' @@ -224,42 +231,44 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Update the user with the same auth string + - name: Plugin auth | Update the user with the same auth string mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_auth_string: '{{ test_plugin_auth_string }}' register: result # This is the current expected behavior because there isn't a reliable way to hash the password in the mysql_user # module in order to be able to compare this password with the stored hash. See the source for more info. - - name: The module should detect a change even though the password is the same + - name: Plugin auth | The module should detect a change even though the password is the same assert: that: - result is changed - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Change the user using the same plugin, but switch to the same auth string in hash form + - name: Plugin auth | Change the user using the same plugin, but switch to the same auth string in hash form mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' plugin_hash_string: '{{ test_plugin_hash }}' register: result - - name: Check that the module did not change the password + - name: Plugin auth | Check that the module did not change the password assert: that: - result is not changed - - name: Get the MySQL version using the newly created creds + - name: Plugin auth | Get the MySQL version using the newly created creds mysql_info: login_user: '{{ test_user_name }}' login_password: '{{ test_plugin_auth_string }}' @@ -268,44 +277,45 @@ filter: version register: result - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test plugin auth with an empty auth string. # - - name: Create user with plugin auth (empty auth string) + - name: Plugin auth | Create user with plugin auth (empty auth string) mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' priv: '{{ test_default_priv }}' register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + - name: Plugin auth | Get user information (empty auth string) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'%'\"" register: show_create_user - - name: Check that the module made a change + - name: Plugin auth | Check that the module made a change (empty auth string) assert: that: - result is changed - - name: Check that the expected plugin type is set + - name: Plugin auth | Check that the expected plugin type is set (empty auth string) assert: that: - "'{{ test_plugin_type }}' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }} - - name: Get the MySQL version using an empty password for the newly created user + - name: Plugin auth | Get the MySQL version using an empty password for the newly created user mysql_info: login_user: '{{ test_user_name }}' login_password: '' @@ -315,12 +325,12 @@ register: result ignore_errors: true - - name: Assert that mysql_info was successful + - name: Plugin auth | Assert that mysql_info was successful assert: that: - result is succeeded - - name: Get the MySQL version using an non-empty password (should fail) + - name: Plugin auth | Get the MySQL version using an non-empty password (should fail) mysql_info: login_user: '{{ test_user_name }}' login_password: 'some_password' @@ -330,91 +340,92 @@ register: result ignore_errors: true - - name: Assert that mysql_info failed + - name: Plugin auth | Assert that mysql_info failed assert: that: - result is failed - - name: Update the user without changing the auth mechanism + - name: Plugin auth | Update the user without changing the auth mechanism mysql_user: <<: *mysql_params name: '{{ test_user_name }}' + host: '%' plugin: '{{ test_plugin_type }}' state: present register: result - - name: Assert that the user wasn't changed because the auth string is still empty + - name: Plugin auth | Assert that the user wasn't changed because the auth string is still empty assert: that: - result is not changed # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} + - include: utils/remove_user.yml user_name={{ test_user_name }} # ============================================================ # Test plugin auth switching from one type of plugin to another without an auth string or hash. The only other # plugins that are loaded by default are sha2*, but these aren't compatible with pymysql < 0.9, so skip these tests # for those versions. # - - name: Test plugin auth switching which doesn't work on pymysql < 0.9 + - name: Plugin auth | Test plugin auth switching which doesn't work on pymysql < 0.9 when: - > - connector_name is not search('pymysql') + connector_name != 'pymysql' or ( - connector_name is search('pymysql') - and connector_ver is version('0.9', '>=') + connector_name == 'pymysql' + and connector_version is version('0.9', '>=') ) block: - - name: Create user with plugin auth (empty auth string) - mysql_user: - <<: *mysql_params - name: '{{ test_user_name }}' - plugin: '{{ test_plugin_type }}' - priv: '{{ test_default_priv }}' - register: result + - name: Plugin auth | Create user with plugin auth (empty auth string) + mysql_user: + <<: *mysql_params + name: '{{ test_user_name }}' + plugin: '{{ test_plugin_type }}' + priv: '{{ test_default_priv }}' + register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" - register: show_create_user + - name: Plugin auth | Get user information (empty auth string) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + register: show_create_user - - name: Check that the module made a change - assert: - that: - - result is changed + - name: Plugin auth | Check that the module made a change (empty auth string) + assert: + that: + - result is changed - - name: Check that the expected plugin type is set - assert: - that: - - "'{{ test_plugin_type }}' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + - name: Plugin auth | Check that the expected plugin type is set (empty auth string) + assert: + that: + - test_plugin_type in show_create_user.stdout + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }} - - name: Switch user to sha256_password auth plugin - mysql_user: - <<: *mysql_params - name: '{{ test_user_name }}' - plugin: sha256_password - priv: '{{ test_default_priv }}' - register: result + - name: Plugin auth | Switch user to sha256_password auth plugin + mysql_user: + <<: *mysql_params + name: '{{ test_user_name }}' + plugin: sha256_password + priv: '{{ test_default_priv }}' + register: result - - name: Get user information - command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" - register: show_create_user + - name: Plugin auth | Get user information (sha256_password) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + register: show_create_user - - name: Check that the module made a change - assert: - that: - - result is changed + - name: Plugin auth | Check that the module made a change (sha256_password) + assert: + that: + - result is changed - - name: Check that the expected plugin type is set - assert: - that: + - name: Plugin auth | Check that the expected plugin type is set (sha256_password) + assert: + that: - "'sha256_password' in show_create_user.stdout" - when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>=')) + when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>=')) - - include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }} + - include: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }} - # Cleanup - - include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }} + # Cleanup + - include: utils/remove_user.yml user_name={{ test_user_name }} diff --git a/tests/integration/targets/test_mysql_user/tasks/utils/assert_no_user.yml b/tests/integration/targets/test_mysql_user/tasks/utils/assert_no_user.yml new file mode 100644 index 0000000..6fc4fbc --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/utils/assert_no_user.yml @@ -0,0 +1,8 @@ +--- +- name: Utils | Assert no user | Query for user {{ user_name }} + command: "{{ mysql_command }} -e \"SELECT User FROM mysql.user where user='{{ user_name }}'\"" + register: result + +- name: Utils | Assert no user | Assert mysql user is not present + assert: + that: user_name not in result.stdout diff --git a/tests/integration/targets/test_mysql_user/tasks/utils/assert_user.yml b/tests/integration/targets/test_mysql_user/tasks/utils/assert_user.yml new file mode 100644 index 0000000..e6bd23f --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/utils/assert_user.yml @@ -0,0 +1,21 @@ +--- + +- name: Utils | Assert user | Query for user {{ user_name }} + command: "{{ mysql_command }} -e \"SELECT user FROM mysql.user where user='{{ user_name }}'\"" + register: result + +- name: Utils | Assert user | Assert user is present + assert: + that: + - user_name in result.stdout + +- name: Utils | Assert user | Query for privileges of user {{ user_name }} + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name }}'@'{{ user_host }}'\"" + register: result + when: priv is defined + +- name: Utils | Assert user | Assert user has given privileges + ansible.builtin.assert: + that: + - "'GRANT {{ priv }} ON *.*' in result.stdout" + when: priv is defined diff --git a/tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml b/tests/integration/targets/test_mysql_user/tasks/utils/assert_user_password.yml similarity index 73% rename from tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml rename to tests/integration/targets/test_mysql_user/tasks/utils/assert_user_password.yml index ba045eb..d95e53b 100644 --- a/tests/integration/targets/test_mysql_user/tasks/assert_user_password.yml +++ b/tests/integration/targets/test_mysql_user/tasks/utils/assert_user_password.yml @@ -1,4 +1,5 @@ -- name: "applying user {{ username }}@{{ host }} with update_password={{ update_password }}" +--- +- name: Utils | Assert user password | Apply update_password to {{ username }} mysql_user: login_user: '{{ mysql_parameters.login_user }}' login_password: '{{ mysql_parameters.login_password }}' @@ -10,15 +11,18 @@ password: "{{ password }}" update_password: "{{ update_password }}" register: result -- name: assert a change occurred + +- name: Utils | Assert user password | Assert a change occurred assert: that: - "result.changed | bool == {{ expect_change }} | bool" - "result.password_changed == {{ expect_password_change }}" -- name: query the user + +- name: Utils | Assert user password | Query user {{ username }} command: "{{ mysql_command }} -BNe \"SELECT plugin, authentication_string FROM mysql.user where user='{{ username }}' and host='{{ host }}'\"" register: existing_user -- name: assert the password is as set to expect_hash + +- name: Utils | Assert user password | Assert expect_hash is in user stdout assert: that: - "'mysql_native_password\t{{ expect_password_hash }}' in existing_user.stdout_lines" diff --git a/tests/integration/targets/test_mysql_user/tasks/utils/create_user.yml b/tests/integration/targets/test_mysql_user/tasks/utils/create_user.yml new file mode 100644 index 0000000..b255ec4 --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/utils/create_user.yml @@ -0,0 +1,12 @@ +--- + +- name: Utils | Create user {{ user_name }} + mysql_user: + login_user: "{{ mysql_user }}" + login_password: "{{ mysql_password }}" + login_host: "{{ mysql_host }}" + login_port: "{{ mysql_primary_port }}" + name: "{{ user_name }}" + host: "{{ user_host | default(omit) }}" + password: "{{ user_password }}" + state: present diff --git a/tests/integration/targets/test_mysql_user/tasks/utils/remove_user.yml b/tests/integration/targets/test_mysql_user/tasks/utils/remove_user.yml new file mode 100644 index 0000000..473cece --- /dev/null +++ b/tests/integration/targets/test_mysql_user/tasks/utils/remove_user.yml @@ -0,0 +1,12 @@ +--- + +- name: Utils | Remove user {{ user_name }} + mysql_user: + login_user: "{{ mysql_user }}" + login_password: "{{ mysql_password }}" + login_host: "{{ mysql_host }}" + login_port: "{{ mysql_primary_port }}" + name: "{{ user_name }}" + host_all: true + state: absent + ignore_errors: true diff --git a/tests/integration/targets/test_mysql_variables/defaults/main.yml b/tests/integration/targets/test_mysql_variables/defaults/main.yml index 6d0e2ec..779eead 100644 --- a/tests/integration/targets/test_mysql_variables/defaults/main.yml +++ b/tests/integration/targets/test_mysql_variables/defaults/main.yml @@ -2,6 +2,7 @@ # defaults file for test_mysql_variables mysql_user: root mysql_password: msandbox +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 user_name_1: 'db_user1' diff --git a/tests/integration/targets/test_mysql_variables/meta/main.yml b/tests/integration/targets/test_mysql_variables/meta/main.yml index f1174ff..01ee3db 100644 --- a/tests/integration/targets/test_mysql_variables/meta/main.yml +++ b/tests/integration/targets/test_mysql_variables/meta/main.yml @@ -1,2 +1,3 @@ +--- dependencies: - - setup_mysql + - setup_controller diff --git a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml index 96d196d..e64c5a7 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/assert_var.yml @@ -1,3 +1,4 @@ +--- # test code to assert variables in mysql_variables module # (c) 2014, Wayne Rosario @@ -19,16 +20,16 @@ # ============================================================ # Assert mysql variable name and value from mysql database # -- name: assert output message changed value +- name: Assert output message changed value assert: that: - "output.changed | bool == changed | bool" -- name: run mysql command to show variable +- name: Run mysql command to show variable command: "{{ mysql_command }} \"-e show variables like '{{ var_name }}'\"" register: result -- name: assert output mysql variable name and value +- name: Assert output mysql variable name and value assert: that: - result is changed diff --git a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml index dadfb87..def6d8b 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/issue-28.yml @@ -9,7 +9,7 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' when: tls_enabled block: @@ -26,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -33,6 +34,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: '%' password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' tls_requires: @@ -43,7 +45,7 @@ variable: '{{ set_name }}' login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem register: result @@ -52,19 +54,21 @@ - assert: that: - result is failed - when: connector_name is search('pymysql') + when: + - connector_name == 'pymysql' - assert: that: - result is succeeded - when: connector_name is not search('pymysql') + when: + - connector_name != 'pymysql' - name: attempt connection with newly created user ignoring hostname mysql_variables: variable: '{{ set_name }}' login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' ca_cert: /tmp/cert.pem check_hostname: no @@ -79,5 +83,5 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' - host: 127.0.0.1 + host_all: true state: absent diff --git a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml index ed34966..c8ae3e8 100644 --- a/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml +++ b/tests/integration/targets/test_mysql_variables/tasks/mysql_variables.yml @@ -23,15 +23,11 @@ mysql_parameters: &mysql_params login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' block: - - name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp" - - set_fact: set_name: 'version' @@ -151,7 +147,7 @@ # ============================================================ # Verify mysql_variable fails when setting an incorrect value (out of range) # - - name: set mysql variable value to a number out of range + - name: Set mysql variable value to a number out of range mysql_variables: <<: *mysql_params variable: max_connect_errors @@ -160,10 +156,13 @@ ignore_errors: true - include: assert_var.yml changed=true output={{ oor_result }} var_name=max_connect_errors var_value=1 - when: connector_name is not search('pymysql') + when: + - connector_name == 'mysqlclient' + - db_engine == 'mysql' # mysqlclient returns "changed" with MariaDB - include: assert_fail_msg.yml output={{ oor_result }} msg='Truncated incorrect' - when: connector_name is search('pymysql') + when: + - connector_name == 'pymsql' # ============================================================ # Verify mysql_variable fails when setting an incorrect value (incorrect type) @@ -246,7 +245,7 @@ mysql_variables: login_user: '{{ mysql_user }}' login_password: 'wrongpassword' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' variable: '{{ set_name }}' register: result @@ -258,7 +257,7 @@ mysql_variables: login_user: '{{ mysql_user }}' login_password: 'wrongpassword' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' variable: '{{ set_name }}' value: '{{ set_value }}' @@ -360,8 +359,8 @@ - include: assert_var.yml changed=true output={{ result }} var_name={{ set_name }} var_value='{{ def_val }}' when: - - mysql_version is version('8.0', '>=') - - install_type == 'mysql' + - db_engine == 'mysql' + - db_version is version('8.0', '>=') # Bugfix of https://github.com/ansible/ansible/issues/54239 # - name: set variable containing dot diff --git a/tests/integration/test_connection.yml b/tests/integration/test_connection.yml new file mode 100644 index 0000000..160cfba --- /dev/null +++ b/tests/integration/test_connection.yml @@ -0,0 +1,81 @@ +--- + +- name: Playbook to test bug to connect to MySQL/MariaDB server + hosts: all + gather_facts: false + vars: + mysql_parameters: &mysql_params + login_user: '{{ mysql_user }}' + login_password: '{{ mysql_password }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + tasks: + + # Create default MySQL config file with credentials + - name: mysql_info - create default config file + template: + src: my.cnf.j2 + dest: /root/.my.cnf + mode: '0400' + + # Create non-default MySQL config file with credentials + - name: mysql_info - create non-default config file + template: + src: tests/integration/targets/test_mysql_info/templates/my.cnf.j2 + dest: /root/non-default_my.cnf + mode: '0400' + + ############### + # Do tests + + # Access by default cred file + - name: mysql_info - collect default cred file + mysql_info: + login_user: '{{ mysql_user }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + register: result + + - assert: + that: + - result is not changed + - db_version in result.version.full + - result.settings != {} + - result.global_status != {} + - result.databases != {} + - result.engines != {} + - result.users != {} + + # Access by non-default cred file + - name: mysql_info - check non-default cred file + mysql_info: + login_user: '{{ mysql_user }}' + login_host: '{{ mysql_host }}' + login_port: '{{ mysql_primary_port }}' + config_file: /root/non-default_my.cnf + register: result + + - assert: + that: + - result is not changed + - result.version != {} + + # Remove cred files + - name: mysql_info - remove cred files + file: + path: '{{ item }}' + state: absent + with_items: + - /root/.my.cnf + - /root/non-default_my.cnf + + # Access with password + - name: mysql_info - check access with password + mysql_info: + <<: *mysql_params + register: result + + - assert: + that: + - result is not changed + - result.version != {} From 3e975ca7a12190e4c95f353c231bc410b2ef338c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Thu, 30 Mar 2023 08:25:54 +0200 Subject: [PATCH 59/63] [PR #514/e2aa655 backport][stable-1] Fix issues and documentation with integration tests after merge of #490 (#520) * Fix issues and documentation with integration tests after merge of #490. (#514) * Fix explanation about containers images * Add definitive URI to the containers images * Document that new images must be set as public * Document makefile options possible values * Document that any mysql and mariadb tag can be used * Add computation of docker_image path * Refactor pre-command to separate commands for cleaner GHA output * Refactor to use GHA test matrix * Cut docker_image from documentation since it's now automatic * Document how to use run_all_test.py to display the test matrix (cherry picked from commit e2aa655762a9ac5c7343a6f53e9aed1c2d86b629) * Add changelog fragment * Cut tests for MariaDB 10.5 and 10.6 that never worked with stable-1 --- .github/workflows/ansible-test-plugins.yml | 419 ++++++++---------- ...ker-image-mariadb-py310-mysqlclient211.yml | 19 + .../docker-image-mariadb-py310-pymysql102.yml | 19 + ...cker-image-mariadb-py38-mysqlclient201.yml | 19 + .../docker-image-mariadb-py38-pymysql093.yml | 19 + ...cker-image-mariadb-py39-mysqlclient203.yml | 19 + .../docker-image-mariadb-py39-pymysql093.yml | 19 + ...r-image-mariadb103-py38-mysqlclient201.yml | 19 - ...ocker-image-mariadb103-py38-pymysql093.yml | 19 - ...r-image-mariadb103-py39-mysqlclient203.yml | 19 - ...ocker-image-mariadb103-py39-pymysql093.yml | 19 - ...-image-mariadb106-py310-mysqlclient211.yml | 19 - ...cker-image-mariadb106-py310-pymysql102.yml | 19 - ...docker-image-my80-py310-mysqlclient211.yml | 19 - .../docker-image-my80-py310-pymysql102.yml | 19 - .../docker-image-my80-py38-mysqlclient201.yml | 19 - .../docker-image-my80-py38-pymysql093.yml | 19 - .../docker-image-my80-py39-mysqlclient203.yml | 19 - .../docker-image-my80-py39-pymysql093.yml | 19 - ...ocker-image-mysql-py310-mysqlclient211.yml | 19 + .../docker-image-mysql-py310-pymysql102.yml | 19 + ...docker-image-mysql-py38-mysqlclient201.yml | 19 + .../docker-image-mysql-py38-pymysql093.yml | 19 + ...docker-image-mysql-py39-mysqlclient203.yml | 19 + .../docker-image-mysql-py39-pymysql093.yml | 19 + Makefile | 42 +- TESTING.md | 135 ++++-- .../fragments/backport-stable-1-pr-514.yml | 3 + run_all_tests.py | 95 ++-- .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../Dockerfile | 0 .../setup_controller/tasks/setvars.yml | 24 +- 42 files changed, 640 insertions(+), 534 deletions(-) create mode 100644 .github/workflows/docker-image-mariadb-py310-mysqlclient211.yml create mode 100644 .github/workflows/docker-image-mariadb-py310-pymysql102.yml create mode 100644 .github/workflows/docker-image-mariadb-py38-mysqlclient201.yml create mode 100644 .github/workflows/docker-image-mariadb-py38-pymysql093.yml create mode 100644 .github/workflows/docker-image-mariadb-py39-mysqlclient203.yml create mode 100644 .github/workflows/docker-image-mariadb-py39-pymysql093.yml delete mode 100644 .github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml delete mode 100644 .github/workflows/docker-image-mariadb103-py38-pymysql093.yml delete mode 100644 .github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml delete mode 100644 .github/workflows/docker-image-mariadb103-py39-pymysql093.yml delete mode 100644 .github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml delete mode 100644 .github/workflows/docker-image-mariadb106-py310-pymysql102.yml delete mode 100644 .github/workflows/docker-image-my80-py310-mysqlclient211.yml delete mode 100644 .github/workflows/docker-image-my80-py310-pymysql102.yml delete mode 100644 .github/workflows/docker-image-my80-py38-mysqlclient201.yml delete mode 100644 .github/workflows/docker-image-my80-py38-pymysql093.yml delete mode 100644 .github/workflows/docker-image-my80-py39-mysqlclient203.yml delete mode 100644 .github/workflows/docker-image-my80-py39-pymysql093.yml create mode 100644 .github/workflows/docker-image-mysql-py310-mysqlclient211.yml create mode 100644 .github/workflows/docker-image-mysql-py310-pymysql102.yml create mode 100644 .github/workflows/docker-image-mysql-py38-mysqlclient201.yml create mode 100644 .github/workflows/docker-image-mysql-py38-pymysql093.yml create mode 100644 .github/workflows/docker-image-mysql-py39-mysqlclient203.yml create mode 100644 .github/workflows/docker-image-mysql-py39-pymysql093.yml create mode 100644 changelogs/fragments/backport-stable-1-pr-514.yml rename test-containers/{mariadb106-py310-mysqlclient211 => mariadb-py310-mysqlclient211}/Dockerfile (100%) rename test-containers/{mariadb106-py310-pymysql102 => mariadb-py310-pymysql102}/Dockerfile (100%) rename test-containers/{mariadb103-py38-mysqlclient201 => mariadb-py38-mysqlclient201}/Dockerfile (100%) rename test-containers/{mariadb103-py38-pymysql093 => mariadb-py38-pymysql093}/Dockerfile (100%) rename test-containers/{mariadb103-py39-mysqlclient203 => mariadb-py39-mysqlclient203}/Dockerfile (100%) rename test-containers/{mariadb103-py39-pymysql093 => mariadb-py39-pymysql093}/Dockerfile (100%) rename test-containers/{my80-py310-mysqlclient211 => mysql-py310-mysqlclient211}/Dockerfile (100%) rename test-containers/{my80-py310-pymysql102 => mysql-py310-pymysql102}/Dockerfile (100%) rename test-containers/{my80-py38-mysqlclient201 => mysql-py38-mysqlclient201}/Dockerfile (100%) rename test-containers/{my80-py38-pymysql093 => mysql-py38-pymysql093}/Dockerfile (100%) rename test-containers/{my80-py39-mysqlclient203 => mysql-py39-mysqlclient203}/Dockerfile (100%) rename test-containers/{my80-py39-pymysql093 => mysql-py39-pymysql093}/Dockerfile (100%) diff --git a/.github/workflows/ansible-test-plugins.yml b/.github/workflows/ansible-test-plugins.yml index 88d8fce..3e57cb9 100644 --- a/.github/workflows/ansible-test-plugins.yml +++ b/.github/workflows/ansible-test-plugins.yml @@ -35,12 +35,35 @@ jobs: pull-request-change-detection: true integration: - name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.db_engine_version }}, Connector: ${{ matrix.connector }})" + name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, DB: ${{ matrix.db_engine_name }} ${{ matrix.db_engine_version }}, connector: ${{ matrix.connector_name }} ${{ matrix.connector_version }})" runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: - include: + ansible: + - stable-2.12 + - stable-2.13 + - stable-2.14 + - devel + db_engine_name: + - mysql + - mariadb + db_engine_version: + - 5.7.40 + - 8.0.31 + - 10.4.27 + # - 10.5.18 + # - 10.6.11 + python: + - '3.8' + - '3.9' + - '3.10' + connector_name: + - pymysql + - mysqlclient + connector_version: + - 0.7.11 + - 0.9.3 # Before we can activate test with pymysql 1.0.2 we should debug the # following plugins: # @@ -49,244 +72,128 @@ jobs: # # mysql_replication: # test "Assert that startreplica is not changed" failed + # - 1.0.2 + - 2.0.1 + - 2.0.3 + - 2.1.1 + exclude: + - db_engine_name: mysql + db_engine_version: 10.4.27 - # ================================================================== - # mysql-client 5.7 + Python 3.8 - # ================================================================== - - ansible: stable-2.12 - db_engine_version: mysql:5.7.40 - python: '3.8' - connector: pymysql==0.7.11 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-pymysql0711:latest - - ansible: stable-2.12 - db_engine_version: mysql:5.7.40 - python: '3.8' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-pymysql093:latest - - ansible: stable-2.12 - db_engine_version: mysql:5.7.40 - python: '3.8' - connector: mysqlclient==2.0.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my57-py38-mysqlclient201:latest + - db_engine_name: mysql + db_engine_version: 10.5.18 + - db_engine_name: mysql + db_engine_version: 10.6.11 - # ================================================================== - # mysql-client 8 + Python 3.8 - # ================================================================== - - ansible: stable-2.12 - db_engine_version: mysql:8.0.31 - python: '3.8' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py38-pymysql093:latest - - ansible: stable-2.12 - db_engine_version: mysql:8.0.31 - python: '3.8' - connector: mysqlclient==2.0.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py38-mysqlclient201:latest + - db_engine_name: mariadb + db_engine_version: 5.7.40 + - db_engine_name: mariadb + db_engine_version: 8.0.31 - # ================================================================== - # mysql-client 8 + Python 3.9 - # ================================================================== - - ansible: stable-2.13 - db_engine_version: mysql:8.0.31 + - connector_name: pymysql + connector_version: 2.0.1 + + - connector_name: pymysql + connector_version: 2.0.3 + + - connector_name: pymysql + connector_version: 2.1.1 + + - connector_name: mysqlclient + connector_version: 0.7.11 + + - connector_name: mysqlclient + connector_version: 0.9.3 + + - connector_name: mysqlclient + connector_version: 1.0.2 + + - db_engine_name: mariadb + connector_version: 0.7.11 + + - db_engine_version: 5.7.40 python: '3.9' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-pymysql093:latest - - ansible: stable-2.13 - db_engine_version: mysql:8.0.31 - python: '3.9' - connector: mysqlclient==2.0.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-mysqlclient203:latest - - ansible: stable-2.14 - db_engine_version: mysql:8.0.31 - python: '3.9' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-pymysql093:latest - - ansible: stable-2.14 - db_engine_version: mysql:8.0.31 - python: '3.9' - connector: mysqlclient==2.0.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py39-mysqlclient203:latest - - - # ================================================================== - # mysql-client 8 + Python 3.10 - # ================================================================== - # - ansible: stable-2.13 - # db_engine_version: mysql:8.0.31 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest - - ansible: stable-2.13 - db_engine_version: mysql:8.0.31 + - db_engine_version: 5.7.40 python: '3.10' - connector: mysqlclient==2.1.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest - # - ansible: stable-2.14 - # db_engine_version: mysql:8.0.31 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest - - ansible: stable-2.14 - db_engine_version: mysql:8.0.31 - python: '3.10' - connector: mysqlclient==2.1.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest + - db_engine_version: 5.7.40 + ansible: stable-2.13 - # - ansible: devel - # db_engine_version: mysql:8.0.31 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-pymysql102:latest - - ansible: devel - db_engine_version: mysql:8.0.31 - python: '3.10' - connector: mysqlclient==2.1.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-my80-py310-mysqlclient211:latest + - db_engine_version: 5.7.40 + ansible: stable-2.14 - # ================================================================== - # mariadb-client 10.3 + Python 3.8 - # ================================================================== - - ansible: stable-2.12 - db_engine_version: mariadb:10.4.27 + - db_engine_version: 5.7.40 + ansible: devel + + - db_engine_version: 8.0.31 python: '3.8' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-pymysql093:latest - - ansible: stable-2.12 - db_engine_version: mariadb:10.4.27 + + - db_engine_version: 8.0.31 python: '3.8' - connector: mysqlclient==2.0.1 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-mysqlclient201:latest - # - ansible: stable-2.12 - # db_engine_version: mariadb:10.5.18 - # python: '3.8' - # connector: pymysql==0.9.3 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-pymysql093:latest - # - ansible: stable-2.12 - # db_engine_version: mariadb:10.5.18 - # python: '3.8' - # connector: mysqlclient==2.0.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py38-mysqlclient201:latest + - db_engine_version: 10.4.27 + python: '3.10' - # ================================================================== - # mariadb-client 10.3 + Python 3.9 - # ================================================================== - - ansible: stable-2.13 - db_engine_version: mariadb:10.4.27 + - db_engine_version: 10.4.27 + ansible: devel + + - db_engine_version: 10.6.11 + python: '3.8' + + - db_engine_version: 10.6.11 python: '3.9' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest - - ansible: stable-2.13 - db_engine_version: mariadb:10.4.27 - python: '3.9' - connector: mysqlclient==2.0.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.5.18 - # python: '3.9' - # connector: pymysql==0.9.3 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.5.18 - # python: '3.9' - # connector: mysqlclient==2.0.3 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest - - ansible: stable-2.14 - db_engine_version: mariadb:10.4.27 - python: '3.9' - connector: pymysql==0.9.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest - - ansible: stable-2.14 - db_engine_version: mariadb:10.4.27 - python: '3.9' - connector: mysqlclient==2.0.3 - docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.5.18 - # python: '3.9' - # connector: pymysql==0.9.3 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-pymysql093:latest - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.5.18 - # python: '3.9' - # connector: mysqlclient==2.0.3 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb103-py39-mysqlclient203:latest + - python: '3.8' + connector_version: 2.0.3 + - python: '3.8' + connector_version: 2.1.1 - # ================================================================== - # mariadb-client 10.6 + Python 3.10 - # ================================================================== - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: stable-2.13 - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + - python: '3.9' + connector_version: 0.7.11 - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: stable-2.14 - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + - python: '3.9' + connector_version: 2.0.1 - # - ansible: devel - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: devel - # db_engine_version: mariadb:10.5.18 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest - # - ansible: devel - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: pymysql==1.0.2 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-pymysql102:latest - # - ansible: devel - # db_engine_version: mariadb:10.6.11 - # python: '3.10' - # connector: mysqlclient==2.1.1 - # docker_image: ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest + - python: '3.9' + connector_version: 2.1.1 + + - python: '3.10' + connector_version: 0.7.11 + + - python: '3.10' + connector_version: 0.9.3 + + - python: '3.10' + connector_version: 2.0.1 + + - python: '3.10' + connector_version: 2.0.3 + + - python: '3.8' + ansible: stable-2.13 + + - python: '3.8' + ansible: stable-2.14 + + - python: '3.8' + ansible: devel + + - python: '3.9' + ansible: stable-2.12 + + - python: '3.9' + ansible: devel + + - python: '3.10' + ansible: stable-2.12 services: db_primary: - image: docker.io/library/${{ matrix.db_engine_version }} + image: docker.io/library/${{ matrix.db_engine_name }}:${{ matrix.db_engine_version }} env: MARIADB_ROOT_PASSWORD: msandbox MYSQL_ROOT_PASSWORD: msandbox @@ -302,7 +209,7 @@ jobs: --health-retries 6 db_replica1: - image: docker.io/library/${{ matrix.db_engine_version }} + image: docker.io/library/${{ matrix.db_engine_name }}:${{ matrix.db_engine_version }} env: MARIADB_ROOT_PASSWORD: msandbox MYSQL_ROOT_PASSWORD: msandbox @@ -316,7 +223,7 @@ jobs: --health-retries 6 db_replica2: - image: docker.io/library/${{ matrix.db_engine_version }} + image: docker.io/library/${{ matrix.db_engine_name }}:${{ matrix.db_engine_version }} env: MARIADB_ROOT_PASSWORD: msandbox MYSQL_ROOT_PASSWORD: msandbox @@ -343,8 +250,46 @@ jobs: docker restart -t 30 ${{ job.services.db_replica2.id }} - name: Wait for the primary to be healthy - run: | - while ! /usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" ${{ job.services.db_primary.id }} | grep healthy && [[ "$SECONDS" -lt 120 ]]; do sleep 1; done + run: > + while ! /usr/bin/docker inspect + --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" + ${{ job.services.db_primary.id }} + | grep healthy && [[ "$SECONDS" -lt 120 ]]; do sleep 1; done + + - name: Compute docker_image - Set python_version_flat + run: > + echo "python_version_flat=$(echo ${{ matrix.python }} + | tr -d '.')" >> $GITHUB_ENV + + - name: Compute docker_image - Set connector_version_flat + run: > + echo "connector_version_flat=$(echo ${{ matrix.connector_version }} + |tr -d .)" >> $GITHUB_ENV + + - name: Compute docker_image - Set db_engine_version_flat + run: > + echo "db_engine_version_flat=$(echo ${{ matrix.db_engine_version }} + | awk -F '.' '{print $1 $2}')" >> $GITHUB_ENV + + - name: Compute docker_image - Set db_client + run: > + if [[ ${{ env.db_engine_version_flat }} == 57 ]]; then + echo "db_client=my57" >> $GITHUB_ENV; + else + echo "db_client=$(echo ${{ matrix.db_engine_name }})" >> $GITHUB_ENV; + fi + + - name: Set docker_image + run: > + docker_image_multiline=(" + ghcr.io/ansible-collections/community.mysql\ + /test-container-${{ env.db_client }}\ + -py${{ env.python_version_flat }}\ + -${{ matrix.connector_name }}${{ env.connector_version_flat }}\ + :latest") + + echo "docker_image=$(printf '%s' $docker_image_multiline)" + >> $GITHUB_ENV - name: >- Perform integration testing against @@ -354,15 +299,31 @@ jobs: with: ansible-core-version: ${{ matrix.ansible }} pre-test-cmd: >- - echo Setting db_engine_version to "${{ matrix.db_engine_version }}"...; - echo -n "${{ matrix.db_engine_version }}" > tests/integration/db_engine_version; - echo Setting Connector version to "${{ matrix.connector }}"...; - echo -n "${{ matrix.connector }}" > tests/integration/connector; - echo Setting Python version to "${{ matrix.python }}"...; - echo -n "${{ matrix.python }}" > tests/integration/python; - echo Setting Ansible version to "${{ matrix.ansible }}"...; - echo -n "${{ matrix.ansible }}" > tests/integration/ansible - docker-image: ${{ matrix.docker_image }} + echo Setting db_engine_name to "${{ matrix.db_engine_name }}"...; + echo -n "${{ matrix.db_engine_name }}" + > tests/integration/db_engine_name; + + echo Setting db_engine_version to \ + "${{ matrix.db_engine_version }}"...; + echo -n "${{ matrix.db_engine_version }}" + > tests/integration/db_engine_version; + + echo Setting Connector name to "${{ matrix.connector_name }}"...; + echo -n "${{ matrix.connector_name }}" + > tests/integration/connector_name; + + echo Setting Connector name to "${{ matrix.connector_version }}"...; + echo -n "${{ matrix.connector_version }}" + > tests/integration/connector_version; + + echo Setting Python version to "${{ matrix.python }}"...; + echo -n "${{ matrix.python }}" + > tests/integration/python; + + echo Setting Ansible version to "${{ matrix.ansible }}"...; + echo -n "${{ matrix.ansible }}" + > tests/integration/ansible + docker-image: ${{ env.docker_image }} target-python-version: ${{ matrix.python }} testing-type: integration diff --git a/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml b/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml new file mode 100644 index 0000000..a893d3b --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py310-mysqlclient211 + +on: + push: + paths: + - 'test-containers/mariadb-py310-mysqlclient211/**' + - '.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py310-mysqlclient211 + context: test-containers/mariadb-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-mariadb-py310-pymysql102.yml b/.github/workflows/docker-image-mariadb-py310-pymysql102.yml new file mode 100644 index 0000000..dbd8a9d --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py310-pymysql102.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py310-pymysql102 + +on: + push: + paths: + - 'test-containers/mariadb-py310-pymysql102/**' + - '.github/workflows/docker-image-mariadb-py310-pymysql102.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py310-pymysql102 + context: test-containers/mariadb-py310-pymysql102 diff --git a/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml b/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml new file mode 100644 index 0000000..59fcf00 --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py38-mysqlclient201 + +on: + push: + paths: + - 'test-containers/mariadb-py38-mysqlclient201/**' + - '.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py38-mysqlclient201 + context: test-containers/mariadb-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-mariadb-py38-pymysql093.yml b/.github/workflows/docker-image-mariadb-py38-pymysql093.yml new file mode 100644 index 0000000..2602ebe --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py38-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py38-pymysql093 + +on: + push: + paths: + - 'test-containers/mariadb-py38-pymysql093/**' + - '.github/workflows/docker-image-mariadb-py38-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py38-pymysql093 + context: test-containers/mariadb-py38-pymysql093 diff --git a/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml b/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml new file mode 100644 index 0000000..3f260e5 --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py39-mysqlclient203 + +on: + push: + paths: + - 'test-containers/mariadb-py39-mysqlclient203/**' + - '.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py39-mysqlclient203 + context: test-containers/mariadb-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-mariadb-py39-pymysql093.yml b/.github/workflows/docker-image-mariadb-py39-pymysql093.yml new file mode 100644 index 0000000..77bb664 --- /dev/null +++ b/.github/workflows/docker-image-mariadb-py39-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mariadb-py39-pymysql093 + +on: + push: + paths: + - 'test-containers/mariadb-py39-pymysql093/**' + - '.github/workflows/docker-image-mariadb-py39-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mariadb-py39-pymysql093 + context: test-containers/mariadb-py39-pymysql093 diff --git a/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml b/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml deleted file mode 100644 index 3d90270..0000000 --- a/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb103-py38-mysqlclient201 - -on: - push: - paths: - - 'test-containers/mariadb103-py38-mysqlclient201/**' - - '.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb103-py38-mysqlclient201 - context: test-containers/mariadb103-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml b/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml deleted file mode 100644 index 1ca4600..0000000 --- a/.github/workflows/docker-image-mariadb103-py38-pymysql093.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb103-py38-pymysql093 - -on: - push: - paths: - - 'test-containers/mariadb103-py38-pymysql093/**' - - '.github/workflows/docker-image-mariadb103-py38-pymysql093.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb103-py38-pymysql093 - context: test-containers/mariadb103-py38-pymysql093 diff --git a/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml b/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml deleted file mode 100644 index 37e91ee..0000000 --- a/.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb103-py39-mysqlclient203 - -on: - push: - paths: - - 'test-containers/mariadb103-py39-mysqlclient203/**' - - '.github/workflows/docker-image-mariadb103-py39-mysqlclient203.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb103-py39-mysqlclient203 - context: test-containers/mariadb103-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml b/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml deleted file mode 100644 index 30acfc1..0000000 --- a/.github/workflows/docker-image-mariadb103-py39-pymysql093.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb103-py39-pymysql093 - -on: - push: - paths: - - 'test-containers/mariadb103-py39-pymysql093/**' - - '.github/workflows/docker-image-mariadb103-py39-pymysql093.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb103-py39-pymysql093 - context: test-containers/mariadb103-py39-pymysql093 diff --git a/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml b/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml deleted file mode 100644 index 0fa7403..0000000 --- a/.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb106-py310-mysqlclient211 - -on: - push: - paths: - - 'test-containers/mariadb106-py310-mysqlclient211/**' - - '.github/workflows/docker-image-mariadb106-py310-mysqlclient211.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb106-py310-mysqlclient211 - context: test-containers/mariadb106-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml b/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml deleted file mode 100644 index adfe9e3..0000000 --- a/.github/workflows/docker-image-mariadb106-py310-pymysql102.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI mariadb106-py310-pymysql102 - -on: - push: - paths: - - 'test-containers/mariadb106-py310-pymysql102/**' - - '.github/workflows/docker-image-mariadb106-py310-pymysql102.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-mariadb106-py310-pymysql102 - context: test-containers/mariadb106-py310-pymysql102 diff --git a/.github/workflows/docker-image-my80-py310-mysqlclient211.yml b/.github/workflows/docker-image-my80-py310-mysqlclient211.yml deleted file mode 100644 index 824f77c..0000000 --- a/.github/workflows/docker-image-my80-py310-mysqlclient211.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py310-mysqlclient211 - -on: - push: - paths: - - 'test-containers/my80-py310-mysqlclient211/**' - - '.github/workflows/docker-image-my80-py310-mysqlclient211.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py310-mysqlclient211 - context: test-containers/my80-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-my80-py310-pymysql102.yml b/.github/workflows/docker-image-my80-py310-pymysql102.yml deleted file mode 100644 index 0c54e12..0000000 --- a/.github/workflows/docker-image-my80-py310-pymysql102.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py310-pymysql102 - -on: - push: - paths: - - 'test-containers/my80-py310-pymysql102/**' - - '.github/workflows/docker-image-my80-py310-pymysql102.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py310-pymysql102 - context: test-containers/my80-py310-pymysql102 diff --git a/.github/workflows/docker-image-my80-py38-mysqlclient201.yml b/.github/workflows/docker-image-my80-py38-mysqlclient201.yml deleted file mode 100644 index 0ac76b2..0000000 --- a/.github/workflows/docker-image-my80-py38-mysqlclient201.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py38-mysqlclient201 - -on: - push: - paths: - - 'test-containers/my80-py38-mysqlclient201/**' - - '.github/workflows/docker-image-my80-py38-mysqlclient201.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py38-mysqlclient201 - context: test-containers/my80-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-my80-py38-pymysql093.yml b/.github/workflows/docker-image-my80-py38-pymysql093.yml deleted file mode 100644 index 1677be6..0000000 --- a/.github/workflows/docker-image-my80-py38-pymysql093.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py38-pymysql093 - -on: - push: - paths: - - 'test-containers/my80-py38-pymysql093/**' - - '.github/workflows/docker-image-my80-py38-pymysql093.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py38-pymysql093 - context: test-containers/my80-py38-pymysql093 diff --git a/.github/workflows/docker-image-my80-py39-mysqlclient203.yml b/.github/workflows/docker-image-my80-py39-mysqlclient203.yml deleted file mode 100644 index e6b41db..0000000 --- a/.github/workflows/docker-image-my80-py39-mysqlclient203.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py39-mysqlclient203 - -on: - push: - paths: - - 'test-containers/my80-py39-mysqlclient203/**' - - '.github/workflows/docker-image-my80-py39-mysqlclient203.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py39-mysqlclient203 - context: test-containers/my80-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-my80-py39-pymysql093.yml b/.github/workflows/docker-image-my80-py39-pymysql093.yml deleted file mode 100644 index 72ffd60..0000000 --- a/.github/workflows/docker-image-my80-py39-pymysql093.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Docker Image CI my80-py39-pymysql093 - -on: - push: - paths: - - 'test-containers/my80-py39-pymysql093/*' - - '.github/workflows/docker-image-my80-py39-pymysql093.yml' - - '.github/workflows/build-docker-image.yml' - -jobs: - - call-workflow-passing-data: - uses: ./.github/workflows/build-docker-image.yml - secrets: inherit - with: - registry: ghcr.io - image_name: test-container-my80-py39-pymysql093 - context: test-containers/my80-py39-pymysql093 diff --git a/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml b/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml new file mode 100644 index 0000000..70eea1c --- /dev/null +++ b/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py310-mysqlclient211 + +on: + push: + paths: + - 'test-containers/mysql-py310-mysqlclient211/**' + - '.github/workflows/docker-image-mysql-py310-mysqlclient211.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py310-mysqlclient211 + context: test-containers/mysql-py310-mysqlclient211 diff --git a/.github/workflows/docker-image-mysql-py310-pymysql102.yml b/.github/workflows/docker-image-mysql-py310-pymysql102.yml new file mode 100644 index 0000000..bcf88fa --- /dev/null +++ b/.github/workflows/docker-image-mysql-py310-pymysql102.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py310-pymysql102 + +on: + push: + paths: + - 'test-containers/mysql-py310-pymysql102/**' + - '.github/workflows/docker-image-mysql-py310-pymysql102.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py310-pymysql102 + context: test-containers/mysql-py310-pymysql102 diff --git a/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml b/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml new file mode 100644 index 0000000..7fcfb60 --- /dev/null +++ b/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py38-mysqlclient201 + +on: + push: + paths: + - 'test-containers/mysql-py38-mysqlclient201/**' + - '.github/workflows/docker-image-mysql-py38-mysqlclient201.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py38-mysqlclient201 + context: test-containers/mysql-py38-mysqlclient201 diff --git a/.github/workflows/docker-image-mysql-py38-pymysql093.yml b/.github/workflows/docker-image-mysql-py38-pymysql093.yml new file mode 100644 index 0000000..5a43ab8 --- /dev/null +++ b/.github/workflows/docker-image-mysql-py38-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py38-pymysql093 + +on: + push: + paths: + - 'test-containers/mysql-py38-pymysql093/**' + - '.github/workflows/docker-image-mysql-py38-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py38-pymysql093 + context: test-containers/mysql-py38-pymysql093 diff --git a/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml b/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml new file mode 100644 index 0000000..4486a6e --- /dev/null +++ b/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py39-mysqlclient203 + +on: + push: + paths: + - 'test-containers/mysql-py39-mysqlclient203/**' + - '.github/workflows/docker-image-mysql-py39-mysqlclient203.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py39-mysqlclient203 + context: test-containers/mysql-py39-mysqlclient203 diff --git a/.github/workflows/docker-image-mysql-py39-pymysql093.yml b/.github/workflows/docker-image-mysql-py39-pymysql093.yml new file mode 100644 index 0000000..d06dc74 --- /dev/null +++ b/.github/workflows/docker-image-mysql-py39-pymysql093.yml @@ -0,0 +1,19 @@ +--- +name: Docker Image CI mysql-py39-pymysql093 + +on: + push: + paths: + - 'test-containers/mysql-py39-pymysql093/*' + - '.github/workflows/docker-image-mysql-py39-pymysql093.yml' + - '.github/workflows/build-docker-image.yml' + +jobs: + + call-workflow-passing-data: + uses: ./.github/workflows/build-docker-image.yml + secrets: inherit + with: + registry: ghcr.io + image_name: test-container-mysql-py39-pymysql093 + context: test-containers/mysql-py39-pymysql093 diff --git a/Makefile b/Makefile index a94ffd8..dc6d6d0 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,32 @@ ifdef continue_on_errors _continue_on_errors = --retry-on-error --continue-on-error endif + +db_ver_tuple := $(subst ., , $(db_engine_version)) +db_engine_version_flat := $(word 1, $(db_ver_tuple))$(word 2, $(db_ver_tuple)) + +con_ver_tuple := $(subst ., , $(connector_version)) +connector_version_flat := $(word 1, $(con_ver_tuple))$(word 2, $(con_ver_tuple))$(word 3, $(con_ver_tuple)) + +py_ver_tuple := $(subst ., , $(python)) +python_version_flat := $(word 1, $(py_ver_tuple))$(word 2, $(py_ver_tuple)) + +ifeq ($(db_engine_version_flat), 57) + db_client := my57 +else + db_client := $(db_engine_name) +endif + + .PHONY: test-integration test-integration: - echo -n $(db_engine_version) > tests/integration/db_engine_version - echo -n $(connector) > tests/integration/connector - echo -n $(python) > tests/integration/python - echo -n $(ansible) > tests/integration/ansible + @echo -n $(db_engine_name) > tests/integration/db_engine_name + @echo -n $(db_engine_version) > tests/integration/db_engine_version + @echo -n $(connector_name) > tests/integration/connector_name + @echo -n $(connector_version) > tests/integration/connector_version + @echo -n $(python) > tests/integration/python + @echo -n $(ansible) > tests/integration/ansible + # Create podman network for systems missing it. Error can be ignored podman network create podman || true podman run \ @@ -28,7 +48,7 @@ test-integration: --network podman \ --publish 3307:3306 \ --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ - docker.io/library/$(db_engine_version) \ + docker.io/library/$(db_engine_name):$(db_engine_version) \ mysqld podman run \ --detach \ @@ -39,7 +59,7 @@ test-integration: --network podman \ --publish 3308:3306 \ --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ - docker.io/library/$(db_engine_version) \ + docker.io/library/$(db_engine_name):$(db_engine_version) \ mysqld podman run \ --detach \ @@ -50,7 +70,7 @@ test-integration: --network podman \ --publish 3309:3306 \ --health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \ - docker.io/library/$(db_engine_version) \ + docker.io/library/$(db_engine_name):$(db_engine_version) \ mysqld # Setup replication and restart containers podman exec primary bash -c 'echo -e [mysqld]\\nserver-id=1\\nlog-bin=/var/lib/mysql/primary-bin > /etc/mysql/conf.d/replication.cnf' @@ -69,9 +89,13 @@ test-integration: source .venv/$(ansible)/bin/activate python$(local_python_version) -m ensurepip python$(local_python_version) -m pip install --disable-pip-version-check https://github.com/ansible/ansible/archive/$(ansible).tar.gz - -set -x; ansible-test integration $(target) -v --color --coverage --diff --docker $(docker_image) --docker-network podman $(_continue_on_errors) $(_keep_containers_alive) --python $(python); set +x + -set -x; ansible-test integration $(target) -v --color --coverage --diff \ + --docker ghcr.io/ansible-collections/community.mysql/test-container-$(db_client)-py$(python_version_flat)-$(connector_name)$(connector_version_flat):latest \ + --docker-network podman $(_continue_on_errors) $(_keep_containers_alive) --python $(python); set +x + rm tests/integration/db_engine_name rm tests/integration/db_engine_version - rm tests/integration/connector + rm tests/integration/connector_name + rm tests/integration/connector_version rm tests/integration/python rm tests/integration/ansible ifndef keep_containers_alive diff --git a/TESTING.md b/TESTING.md index 9aad0f5..a24193a 100644 --- a/TESTING.md +++ b/TESTING.md @@ -2,7 +2,7 @@ This collection uses GitHub Actions to run ansible-test to validate its content. Three type of tests are used: Sanity, Integration and Units. -The tests covers the code for plugins and roles (no role available yet, but tests are ready) and can be found here: +The tests covers plugins and roles (no role available yet, but tests are ready) and can be found here: - Plugins: *.github/workflows/ansible-test-plugins.yml* - Roles: *.github/workflows/ansible-test-roles.yml* (unused yet) @@ -16,48 +16,125 @@ You can use GitHub to run ansible-test either on the community repo or your fork For now, the makefile only supports Podman. + ### Requirements - python >= 3.8 and <= 3.10 - make +- podman - Minimum 15GB of free space on the device storing containers images and volumes. You can use this command to check: `podman system info --format='{{.Store.GraphRoot}}'|xargs findmnt --noheadings --nofsroot --output SOURCE --target|xargs df -h --output=size,used,avail,pcent,target` - Minimum 2GB of RAM +### Custom ansible-test containers + +Our integrations tests use custom containers for ansible-test. Those images have their definition file stored in the directory [test-containers](test-containers/). We build and publish the images on ghcr.io under the ansible-collection namespace: E.G.: +`ghcr.io/ansible-collections/community.mysql/test-container-mariadb106-py310-mysqlclient211:latest`. + +Availables images are listed [here](https://github.com/orgs/ansible-collections/packages). + + ### Makefile options -The Makefile accept the following options: +The Makefile accept the following options -- **local_python_version**: This option can be omitted if your system has a version supported by Ansible. You can check with `python -V`. -- **ansible**: Mandatory version of ansible to install in a venv to run ansible-test. -- **docker_image**: - The container image to use to run our tests. Those images Dockerfile are in https://github.com/community.mysql/test-containers and then pushed to quay.io: E.G.: - `quay.io/mws/community-mysql-test-containers-my57-py38-mysqlclient201-pymysql0711:latest`. Look in the link above for a complete list of available containers. You can also look into `.github/workflows/ansible-test-plugins.yml` - Unfortunatly you must provide the right container_image yourself. And you still need to provides db_engine_version, python, etc... because ansible-test won't do black magic to try to detect what we expect. Explicit is better than implicit anyway. - To minimise the amount of images, pymysql 0.7.11 and mysqlclient are shipped together. -- **db_engine_version**: The name of the container to use for the service containers that will host a primary database and two replicas. Either MYSQL or MariaDB. Use ':' as a separator. Do not use short version, like mysql:8 for instance. Our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. -- **connector**: The name of the python package of the connector along with its version number. Use '==' as a separator. -- **python**: The python version to use in the controller. -- **target** : If omitted, all test targets will run. But you can limit the tests to a single target to speed up your tests. -- **keep_containers_alive**: This option keeps all tree databases containers and the ansible-test container alive at the end of tests or in case of failure. This is useful to enter one of the containers with `podman exec -it bash` for debugging. Rerunning the -test will recreate those containers. -- **continue_on_errors**: Tells ansible-test to retry on errors and also continue on errors. This is the way the GitHub Action's workflow runs the tests. If you develop a new target, this option can be used to validate that your tests cleanup everything so a new run can restart without errors like "Failed to create database x because it already exists". +- `local_python_version` + - Mandatory: false + - Choices: + - "3.8" + - "3.9" + - "3.10" + - Description: If `Python -V` shows an unsupported version, use this option and choose one of the version available on your system. Use `ls /usr/bin/python3*|grep -v config` to list them. -Examples: +- `ansible` + - Mandatory: true + - Choices: + - "stable-2.12" + - "stable-2.13" + - "stable-2.14" + - "devel" + - Description: Version of ansible to install in a venv to run ansible-test + +- `db_engine_name` + - Mandatory: true + - Choices: + - "mysql" + - "mariadb" + - Description: The name of the database engine to use for the service containers that will host a primary database and two replicas. + +- `db_engine_version` + - Mandatory: true + - Choices: + - "5.7.40" <- mysql + - "8.0.31" <- mysql + - "10.4.24" <- mariadb + - "10.5.18" <- mariadb + - "10.6.11" <- mariadb + - Description: The tag of the container to use for the service containers that will host a primary database and two replicas. Do not use short version, like `mysql:8` (don't do that) because our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. You can use any tag available on [hub.docker.com/_/mysql](https://hub.docker.com/_/mysql) and [hub.docker.com/_/mariadb](https://hub.docker.com/_/mariadb) but GitHub Action will only use the versions listed above. + +- `connector_name` + - Mandatory: true + - Choices: + - "pymysql + - "mysqlclient" + - Description: The python package of the connector to use. This value is used to filter tests meant for other connectors. + +- `connector_version` + - Mandatory: true + - Choices: + - "0.7.11" <- Only for MySQL 5.7 + - "0.9.3" + - "1.0.2" <- Not working, need fix + - "2.0.1" + - "2.0.3" + - "2.1.1" + - Description: The version of the python package of the connector to use. This value is used to filter tests meant for other connectors. + +- `python` + - Mandatory: true + - Choices: + - "3.8" + - "3.9" + - "3.10" + - Description: The python version to use in the controller (ansible-test container). + +- `target` + - Mandatory: false + - Choices: + - "test_mysql_db" + - "test_mysql_info" + - "test_mysql_query" + - "test_mysql_replication" + - "test_mysql_role" + - "test_mysql_user" + - "test_mysql_variables" + - Description: If omitted, all test targets will run. But you can limit the tests to a single target to speed up your tests. + +- `keep_containers_alive` + - Mandatory: false + - Description: This option keeps all tree databases containers and the ansible-test container alive at the end of tests or in case of failure. This is useful to enter one of the containers with `podman exec -it bash` for debugging. Rerunning the +test will recreate those containers so no need to kill it. Add any value to activate this option: `keep_containers_alive=1` + +- `continue_on_errors` + - Mandatory: false + - Description: Tells ansible-test to retry on errors and also continue on errors. This is the way the GitHub Action's workflow runs the tests. This can be use to catch all errors in a single run, but you'll need to scroll up to find them. Add any value to activate this option: `continue_on_errors=1` + + +#### Makefile usage examples: ```sh # Run all targets -make ansible="stable-2.12" db_engine_version="mysql:5.7.40" python="3.8" connector="pymysql==0.7.11" docker_image="ghcr.io/community.mysql/test-container-my57-py38-pymysql0711:latest" +make ansible="stable-2.12" db_engine_name="mysql" db_engine_version="5.7.40" python="3.8" connector_name="pymysql" connector_version="0.7.11" # A single target -make ansible="stable-2.14" db_engine_version="mysql:5.7.40" python="3.8" connector="pymysql==0.7.11" docker_image="ghcr.io/community.mysql/test-container-my57-py38-pymysql0711:latest" target="test_mysql_db" +make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="5.7.40" python="3.8" connector_name="pymysql" connector_version="0.7.11" # Keep databases and ansible tests containers alives # A single target and continue on errors -make ansible="stable-2.14" db_engine_version="mysql:8.0.31" python="3.9" connector="mysqlclient==2.0.3" docker_image="ghcr.io/community.mysql/test-container-my80-py39-mysqlclient203:latest" target="test_mysql_db" keep_containers_alive=1 continue_on_errors=1 +make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="8.0.31" python="3.9" connector_name="mysqlclient" connector_version="2.0.3" # If your system has an usupported version of Python: -make local_python_version="3.8" ansible="stable-2.14" db_engine_version="mariadb:10.6.11" python="3.9" connector="pymysql==0.9.3" docker_image="ghcr.io/community.mysql/test-container-mariadb103-py39-pymysql093:latest" +make local_python_version="3.8" ansible="stable-2.14" db_engine_name="mariadb" db_engine_version="10.6.11" python="3.9" connector_name="pymysql" connector_version="0.9.3" ``` @@ -74,14 +151,16 @@ python run_all_tests.py ### Add a new Python, Connector or Database version +You can look into `[.github/workflows/ansible-test-plugins.yml](https://github.com/ansible-collections/community.mysql/tree/main/.github/workflows)` to see how those containers are built using [build-docker-image.yml](https://github.com/ansible-collections/community.mysql/blob/main/.github/workflows/build-docker-image.yml) and all [docker-image-xxx.yml](https://github.com/ansible-collections/community.mysql/blob/main/.github/workflows/docker-image-mariadb103-py38-mysqlclient201.yml) files. + 1. Add a workflow in [.github/workflows/](.github/workflows) 1. Add a new folder in [test-containers](test-containers) containing a new Dockerfile. Your container must contains 3 things: - - The python interpreter - - The python package to connect to the database (pymysql, mysqlclient, ...) - - A mysql client to query the database before to prepare tests before our tests starts. This client must provide both `mysql` and `mysqldump` commands. -1. Add your version in *.github/workflows/ansible-test-plugins.yml* + - Python + - A connector: The python package to connect to the database (pymysql, mysqlclient, ...) + - A mysql client to prepare databases before our tests starts. This client must provide both `mysql` and `mysqldump` commands. +1. Add your version in the matrix of *.github/workflows/ansible-test-plugins.yml*. You can use [run_all_tests.py](run_all_tests.py) to help you see what the matrix will be. Simply comment out the line `os.system(make_cmd)` before runing the script. You can also add `print(len(matrix))` to display how many tests there will be on GitHub Action. +1. Ask the lead maintainer to mark your new image(s) as `public` under [https://github.com/orgs/ansible-collections/packages](https://github.com/orgs/ansible-collections/packages) -After pushing the commit to the remote, the container will be build and published on ghcr.io. Have a look in the "Action" tab to see if it worked. In case of error `failed to copy: io: read/write on closed pipe` re-run the workflow, this append unfortunately a lot. - -To see the docker image produced, go to the main GitHub page of your fork or community.mysql (depending were you pushed) and look for the link "Packages" on the right hand side of the page. This page indicate a "Published x days ago" that is updated infrequently. To see the last time the container has been updated you must click on its title and look in the right hands side bellow the title "Last published". +After pushing your commit to the remote, the container will be built and published on ghcr.io. Have a look in the "Action" tab to see if it worked. In case of error `failed to copy: io: read/write on closed pipe` re-run the workflow, this append unfortunately a lot. +To see the docker image produced, go to the package page in the ansible-collection namespace [https://github.com/orgs/ansible-collections/packages](https://github.com/orgs/ansible-collections/packages). This page indicate a "Published x days ago" that is updated infrequently. To see the last time the container has been updated you must click on its title and look in the right hands side bellow the title "Last published". diff --git a/changelogs/fragments/backport-stable-1-pr-514.yml b/changelogs/fragments/backport-stable-1-pr-514.yml new file mode 100644 index 0000000..b4a351e --- /dev/null +++ b/changelogs/fragments/backport-stable-1-pr-514.yml @@ -0,0 +1,3 @@ +--- +trivial: + - Integration tests - Backport PR514 diff --git a/run_all_tests.py b/run_all_tests.py index b7779a5..94cf799 100755 --- a/run_all_tests.py +++ b/run_all_tests.py @@ -28,54 +28,83 @@ def extract_matrix(workflow_yaml): return matrix -# def is_exclude(exclude_list, test_suite): -# test_is_excluded = False -# for excl in exclude_list: -# match = 0 +def is_exclude(exclude_list, test_suite): + test_is_excluded = False + for excl in exclude_list: + match = 0 -# if 'ansible' in excl: -# if excl.get('ansible') == test_suite[0]: -# match += 1 + if 'ansible' in excl: + if excl.get('ansible') == test_suite.get('ansible'): + match += 1 -# if 'db_engine_version' in excl: -# if excl.get('db_engine_version') == test_suite[1]: -# match += 1 + if 'db_engine_name' in excl: + if excl.get('db_engine_name') == test_suite.get('db_engine_name'): + match += 1 -# if 'python' in excl: -# if excl.get('python') == test_suite[2]: -# match += 1 + if 'db_engine_version' in excl: + if excl.get('db_engine_version') == test_suite.get('db_engine_version'): + match += 1 -# if 'connector' in excl: -# if excl.get('connector') == test_suite[3]: -# match += 1 + if 'python' in excl: + if excl.get('python') == test_suite.get('python'): + match += 1 -# if match > 1: -# test_is_excluded = True + if 'connector_name' in excl: + if excl.get('connector_name') == test_suite.get('connector_name'): + match += 1 -# return test_is_excluded + if 'connector_version' in excl: + if excl.get('connector_version') == test_suite.get('connector_version'): + match += 1 + + if match > 1: + test_is_excluded = True + return test_is_excluded + + return test_is_excluded def main(): workflow_yaml = read_github_workflow_file() tests_matrix_yaml = extract_matrix(workflow_yaml) - # matrix = [] - # exclude_list = tests_matrix_yaml.get('exclude') - # for ansible in tests_matrix_yaml.get('ansible'): - # for db_engine in tests_matrix_yaml.get('db_engine_version'): - # for python in tests_matrix_yaml.get('python'): - # for connector in tests_matrix_yaml.get('connector'): - # if not is_exclude(exclude_list, (ansible, db_engine, python, connector)): - # matrix.append((ansible, db_engine, python, connector)) + matrix = [] + exclude_list = tests_matrix_yaml.get('exclude') + for ansible in tests_matrix_yaml.get('ansible'): + for db_engine_name in tests_matrix_yaml.get('db_engine_name'): + for db_engine_version in tests_matrix_yaml.get('db_engine_version'): + for python in tests_matrix_yaml.get('python'): + for connector_name in tests_matrix_yaml.get('connector_name'): + for connector_version in tests_matrix_yaml.get('connector_version'): + test_suite = { + 'ansible': ansible, + 'db_engine_name': db_engine_name, + 'db_engine_version': db_engine_version, + 'python': python, + 'connector_name': connector_name, + 'connector_version': connector_version + } + if not is_exclude(exclude_list, test_suite): + matrix.append(test_suite) - for tests in tests_matrix_yaml.get('include'): + for tests in matrix: a = tests.get('ansible') - d = tests.get('db_engine_version') + dn = tests.get('db_engine_name') + dv = tests.get('db_engine_version') p = tests.get('python') - c = tests.get('connector') - i = tests.get('docker_image') - make_cmd = f'make ansible="{a}" db_engine_version="{d}" python="{p}" connector="{c}" docker_image="{i}" test-integration' - print(f'Run tests for: Ansible: {a}, DB: {d}, Python: {p}, Connector: {c}, Docker image: {i}') + cn = tests.get('connector_name') + cv = tests.get('connector_version') + make_cmd = ( + f'make ' + f'ansible="{a}" ' + f'db_engine_name="{dn}" ' + f'db_engine_version="{dv}" ' + f'python="{p}" ' + f'connector_name="{cn}" ' + f'connector_version="{cv}" ' + f'test-integration' + ) + print(f'Run tests for: Ansible: {a}, DB: {dn} {dv}, Python: {p}, Connector: {cn} {cv}') os.system(make_cmd) # TODO, allow for CTRL+C to break the loop more easily # TODO, store the failures from this iteration diff --git a/test-containers/mariadb106-py310-mysqlclient211/Dockerfile b/test-containers/mariadb-py310-mysqlclient211/Dockerfile similarity index 100% rename from test-containers/mariadb106-py310-mysqlclient211/Dockerfile rename to test-containers/mariadb-py310-mysqlclient211/Dockerfile diff --git a/test-containers/mariadb106-py310-pymysql102/Dockerfile b/test-containers/mariadb-py310-pymysql102/Dockerfile similarity index 100% rename from test-containers/mariadb106-py310-pymysql102/Dockerfile rename to test-containers/mariadb-py310-pymysql102/Dockerfile diff --git a/test-containers/mariadb103-py38-mysqlclient201/Dockerfile b/test-containers/mariadb-py38-mysqlclient201/Dockerfile similarity index 100% rename from test-containers/mariadb103-py38-mysqlclient201/Dockerfile rename to test-containers/mariadb-py38-mysqlclient201/Dockerfile diff --git a/test-containers/mariadb103-py38-pymysql093/Dockerfile b/test-containers/mariadb-py38-pymysql093/Dockerfile similarity index 100% rename from test-containers/mariadb103-py38-pymysql093/Dockerfile rename to test-containers/mariadb-py38-pymysql093/Dockerfile diff --git a/test-containers/mariadb103-py39-mysqlclient203/Dockerfile b/test-containers/mariadb-py39-mysqlclient203/Dockerfile similarity index 100% rename from test-containers/mariadb103-py39-mysqlclient203/Dockerfile rename to test-containers/mariadb-py39-mysqlclient203/Dockerfile diff --git a/test-containers/mariadb103-py39-pymysql093/Dockerfile b/test-containers/mariadb-py39-pymysql093/Dockerfile similarity index 100% rename from test-containers/mariadb103-py39-pymysql093/Dockerfile rename to test-containers/mariadb-py39-pymysql093/Dockerfile diff --git a/test-containers/my80-py310-mysqlclient211/Dockerfile b/test-containers/mysql-py310-mysqlclient211/Dockerfile similarity index 100% rename from test-containers/my80-py310-mysqlclient211/Dockerfile rename to test-containers/mysql-py310-mysqlclient211/Dockerfile diff --git a/test-containers/my80-py310-pymysql102/Dockerfile b/test-containers/mysql-py310-pymysql102/Dockerfile similarity index 100% rename from test-containers/my80-py310-pymysql102/Dockerfile rename to test-containers/mysql-py310-pymysql102/Dockerfile diff --git a/test-containers/my80-py38-mysqlclient201/Dockerfile b/test-containers/mysql-py38-mysqlclient201/Dockerfile similarity index 100% rename from test-containers/my80-py38-mysqlclient201/Dockerfile rename to test-containers/mysql-py38-mysqlclient201/Dockerfile diff --git a/test-containers/my80-py38-pymysql093/Dockerfile b/test-containers/mysql-py38-pymysql093/Dockerfile similarity index 100% rename from test-containers/my80-py38-pymysql093/Dockerfile rename to test-containers/mysql-py38-pymysql093/Dockerfile diff --git a/test-containers/my80-py39-mysqlclient203/Dockerfile b/test-containers/mysql-py39-mysqlclient203/Dockerfile similarity index 100% rename from test-containers/my80-py39-mysqlclient203/Dockerfile rename to test-containers/mysql-py39-mysqlclient203/Dockerfile diff --git a/test-containers/my80-py39-pymysql093/Dockerfile b/test-containers/mysql-py39-pymysql093/Dockerfile similarity index 100% rename from test-containers/my80-py39-pymysql093/Dockerfile rename to test-containers/mysql-py39-pymysql093/Dockerfile diff --git a/tests/integration/targets/setup_controller/tasks/setvars.yml b/tests/integration/targets/setup_controller/tasks/setvars.yml index d74136d..3e070a9 100644 --- a/tests/integration/targets/setup_controller/tasks/setvars.yml +++ b/tests/integration/targets/setup_controller/tasks/setvars.yml @@ -8,12 +8,22 @@ - name: "{{ role_name }} | Setvars | Set Fact" ansible.builtin.set_fact: gateway_addr: "{{ ip_route_output.stdout }}" - connector_name_version: >- + connector_name_lookup: >- {{ lookup( 'file', - '/root/ansible_collections/community/mysql/tests/integration/connector' + '/root/ansible_collections/community/mysql/tests/integration/connector_name' ) }} - db_engine_version: >- + connector_version_lookup: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/connector_version' + ) }} + db_engine_name_lookup: >- + {{ lookup( + 'file', + '/root/ansible_collections/community/mysql/tests/integration/db_engine_name' + ) }} + db_engine_version_lookup: >- {{ lookup( 'file', '/root/ansible_collections/community/mysql/tests/integration/db_engine_version' @@ -31,10 +41,10 @@ - name: "{{ role_name }} | Setvars | Set Fact using above facts" ansible.builtin.set_fact: - connector_name: "{{ connector_name_version.split('=')[0].strip() }}" - connector_version: "{{ connector_name_version.split('=')[2].strip() }}" - db_engine: "{{ db_engine_version.split(':')[0].strip() }}" - db_version: "{{ db_engine_version.split(':')[1].strip() }}" + connector_name: "{{ connector_name_lookup.strip() }}" + connector_version: "{{ connector_version_lookup.strip() }}" + db_engine: "{{ db_engine_name_lookup.strip() }}" + db_version: "{{ db_engine_version_lookup.strip() }}" python_version: "{{ python_version_lookup.strip() }}" test_ansible_version: >- {%- if ansible_version_lookup == 'devel' -%} From 3ff1f48c41fa3b18c87a241d9fe44685603cb190 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 17:51:54 +0200 Subject: [PATCH 60/63] Add filter to prevent rebuild container on push on stable-(1|2) (#522) (#527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 21e42b57777f803cd5b8c8725ca4eadc43bcbc59) Co-authored-by: Laurent Indermühle --- .github/workflows/docker-image-mariadb-py310-mysqlclient211.yml | 2 ++ .github/workflows/docker-image-mariadb-py310-pymysql102.yml | 2 ++ .github/workflows/docker-image-mariadb-py38-mysqlclient201.yml | 2 ++ .github/workflows/docker-image-mariadb-py38-pymysql093.yml | 2 ++ .github/workflows/docker-image-mariadb-py39-mysqlclient203.yml | 2 ++ .github/workflows/docker-image-mariadb-py39-pymysql093.yml | 2 ++ .github/workflows/docker-image-my57-py38-mysqlclient201.yml | 2 ++ .github/workflows/docker-image-my57-py38-pymysql0711.yml | 2 ++ .github/workflows/docker-image-my57-py38-pymysql093.yml | 2 ++ .github/workflows/docker-image-mysql-py310-mysqlclient211.yml | 2 ++ .github/workflows/docker-image-mysql-py310-pymysql102.yml | 2 ++ .github/workflows/docker-image-mysql-py38-mysqlclient201.yml | 2 ++ .github/workflows/docker-image-mysql-py38-pymysql093.yml | 2 ++ .github/workflows/docker-image-mysql-py39-mysqlclient203.yml | 2 ++ .github/workflows/docker-image-mysql-py39-pymysql093.yml | 2 ++ 15 files changed, 30 insertions(+) diff --git a/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml b/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml index a893d3b..be252b7 100644 --- a/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml +++ b/.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py310-mysqlclient211/**' - '.github/workflows/docker-image-mariadb-py310-mysqlclient211.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mariadb-py310-pymysql102.yml b/.github/workflows/docker-image-mariadb-py310-pymysql102.yml index dbd8a9d..90fec0e 100644 --- a/.github/workflows/docker-image-mariadb-py310-pymysql102.yml +++ b/.github/workflows/docker-image-mariadb-py310-pymysql102.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py310-pymysql102/**' - '.github/workflows/docker-image-mariadb-py310-pymysql102.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml b/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml index 59fcf00..c9c04f4 100644 --- a/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml +++ b/.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py38-mysqlclient201/**' - '.github/workflows/docker-image-mariadb-py38-mysqlclient201.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mariadb-py38-pymysql093.yml b/.github/workflows/docker-image-mariadb-py38-pymysql093.yml index 2602ebe..92d0a74 100644 --- a/.github/workflows/docker-image-mariadb-py38-pymysql093.yml +++ b/.github/workflows/docker-image-mariadb-py38-pymysql093.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py38-pymysql093/**' - '.github/workflows/docker-image-mariadb-py38-pymysql093.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml b/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml index 3f260e5..afad5af 100644 --- a/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml +++ b/.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py39-mysqlclient203/**' - '.github/workflows/docker-image-mariadb-py39-mysqlclient203.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mariadb-py39-pymysql093.yml b/.github/workflows/docker-image-mariadb-py39-pymysql093.yml index 77bb664..1aa5a04 100644 --- a/.github/workflows/docker-image-mariadb-py39-pymysql093.yml +++ b/.github/workflows/docker-image-mariadb-py39-pymysql093.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mariadb-py39-pymysql093/**' - '.github/workflows/docker-image-mariadb-py39-pymysql093.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-my57-py38-mysqlclient201.yml b/.github/workflows/docker-image-my57-py38-mysqlclient201.yml index 2c18f63..7aaf7e3 100644 --- a/.github/workflows/docker-image-my57-py38-mysqlclient201.yml +++ b/.github/workflows/docker-image-my57-py38-mysqlclient201.yml @@ -7,6 +7,8 @@ on: - 'test-containers/my57-py38-mysqlclient201/**' - '.github/workflows/docker-image-my57-py38-mysqlclient201.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-my57-py38-pymysql0711.yml b/.github/workflows/docker-image-my57-py38-pymysql0711.yml index 1568d22..0bc2a9d 100644 --- a/.github/workflows/docker-image-my57-py38-pymysql0711.yml +++ b/.github/workflows/docker-image-my57-py38-pymysql0711.yml @@ -7,6 +7,8 @@ on: - 'test-containers/my57-py38-pymysql0711/**' - '.github/workflows/docker-image-my57-py38-pymysql0711.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-my57-py38-pymysql093.yml b/.github/workflows/docker-image-my57-py38-pymysql093.yml index 39bb583..462324b 100644 --- a/.github/workflows/docker-image-my57-py38-pymysql093.yml +++ b/.github/workflows/docker-image-my57-py38-pymysql093.yml @@ -7,6 +7,8 @@ on: - 'test-containers/my57-py38-pymysql093/**' - '.github/workflows/docker-image-my57-py38-pymysql093.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml b/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml index 70eea1c..307aea7 100644 --- a/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml +++ b/.github/workflows/docker-image-mysql-py310-mysqlclient211.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py310-mysqlclient211/**' - '.github/workflows/docker-image-mysql-py310-mysqlclient211.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py310-pymysql102.yml b/.github/workflows/docker-image-mysql-py310-pymysql102.yml index bcf88fa..6f7bf3f 100644 --- a/.github/workflows/docker-image-mysql-py310-pymysql102.yml +++ b/.github/workflows/docker-image-mysql-py310-pymysql102.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py310-pymysql102/**' - '.github/workflows/docker-image-mysql-py310-pymysql102.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml b/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml index 7fcfb60..e0da5df 100644 --- a/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml +++ b/.github/workflows/docker-image-mysql-py38-mysqlclient201.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py38-mysqlclient201/**' - '.github/workflows/docker-image-mysql-py38-mysqlclient201.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py38-pymysql093.yml b/.github/workflows/docker-image-mysql-py38-pymysql093.yml index 5a43ab8..3cc1e0a 100644 --- a/.github/workflows/docker-image-mysql-py38-pymysql093.yml +++ b/.github/workflows/docker-image-mysql-py38-pymysql093.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py38-pymysql093/**' - '.github/workflows/docker-image-mysql-py38-pymysql093.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml b/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml index 4486a6e..0a3a256 100644 --- a/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml +++ b/.github/workflows/docker-image-mysql-py39-mysqlclient203.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py39-mysqlclient203/**' - '.github/workflows/docker-image-mysql-py39-mysqlclient203.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: diff --git a/.github/workflows/docker-image-mysql-py39-pymysql093.yml b/.github/workflows/docker-image-mysql-py39-pymysql093.yml index d06dc74..b974420 100644 --- a/.github/workflows/docker-image-mysql-py39-pymysql093.yml +++ b/.github/workflows/docker-image-mysql-py39-pymysql093.yml @@ -7,6 +7,8 @@ on: - 'test-containers/mysql-py39-pymysql093/*' - '.github/workflows/docker-image-mysql-py39-pymysql093.yml' - '.github/workflows/build-docker-image.yml' + branches-ignore: + - stable-* jobs: From 011bdbc2efbae0395fce7c29c99f138068faf93e Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 31 Mar 2023 20:25:15 +0200 Subject: [PATCH 61/63] Added formatting behaviour to documentation (#516) (#525) * Added formatting behaviour to documentation * Update plugins/modules/mysql_query.py Co-authored-by: Andrew Klychkov --------- Co-authored-by: Andrew Klychkov (cherry picked from commit 754387c7e520effaf4d05421efe58160f45eff8d) Co-authored-by: IBims1NicerTobi <54948543+IBims1NicerTobi@users.noreply.github.com> --- plugins/modules/mysql_query.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index a3d7ce2..17fa62e 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -22,6 +22,9 @@ options: description: - SQL query to run. Multiple queries can be passed using YAML list syntax. - Must be a string or YAML list containing strings. + - If you use I(named_args) or I(positional_args) any C(%) will be interpreted + as a formatting character. All literal C(%) characters in the query should be + escaped as C(%%). - Note that if you use the C(IF EXISTS/IF NOT EXISTS) clauses in your query and C(mysqlclient) connector, the module will report that the state has been changed even if it has not. If it is important in your From 21a5a8bd0156b78ddce97ca02f6290dd5bc95a77 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 13:30:24 +0200 Subject: [PATCH 62/63] Fix the Makefile for integration tests not using the Python Venv (#532) (#535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix venv not being used by keeping the same shell Also fix "-set -x" command not found. * Fix missing option in the command usage documentation * Document connector-version relationship * Fix missing option in the command usage documentation * Rephrase commands descriptions * Document that you need to kill the ansible-test container yourself (cherry picked from commit 426084a131a280133434aee8f6cfb0d63b24a500) Co-authored-by: Laurent Indermühle --- Makefile | 20 ++++++++++++++------ TESTING.md | 22 +++++++++++----------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index dc6d6d0..7ea0785 100644 --- a/Makefile +++ b/Makefile @@ -86,12 +86,20 @@ test-integration: while ! podman healthcheck run primary && [[ "$$SECONDS" -lt 120 ]]; do sleep 1; done mkdir -p .venv/$(ansible) python$(local_python_version) -m venv .venv/$(ansible) - source .venv/$(ansible)/bin/activate - python$(local_python_version) -m ensurepip - python$(local_python_version) -m pip install --disable-pip-version-check https://github.com/ansible/ansible/archive/$(ansible).tar.gz - -set -x; ansible-test integration $(target) -v --color --coverage --diff \ - --docker ghcr.io/ansible-collections/community.mysql/test-container-$(db_client)-py$(python_version_flat)-$(connector_name)$(connector_version_flat):latest \ - --docker-network podman $(_continue_on_errors) $(_keep_containers_alive) --python $(python); set +x + + # Start venv (use `; \` to keep the same shell) + source .venv/$(ansible)/bin/activate; \ + python$(local_python_version) -m ensurepip; \ + python$(local_python_version) -m pip install --disable-pip-version-check \ + https://github.com/ansible/ansible/archive/$(ansible).tar.gz; \ + set -x; \ + ansible-test integration $(target) -v --color --coverage --diff \ + --docker ghcr.io/ansible-collections/community.mysql/test-container\ + -$(db_client)-py$(python_version_flat)-$(connector_name)$(connector_version_flat):latest \ + --docker-network podman $(_continue_on_errors) $(_keep_containers_alive) --python $(python); \ + set +x + # End of venv + rm tests/integration/db_engine_name rm tests/integration/db_engine_version rm tests/integration/connector_name diff --git a/TESTING.md b/TESTING.md index a24193a..37bbaf6 100644 --- a/TESTING.md +++ b/TESTING.md @@ -77,17 +77,17 @@ The Makefile accept the following options - Choices: - "pymysql - "mysqlclient" - - Description: The python package of the connector to use. This value is used to filter tests meant for other connectors. + - Description: The python package of the connector to use. In addition to selecting the test container, this value is also used for tests filtering: `when: connector_name == 'pymysql'`. - `connector_version` - Mandatory: true - Choices: - - "0.7.11" <- Only for MySQL 5.7 - - "0.9.3" - - "1.0.2" <- Not working, need fix - - "2.0.1" - - "2.0.3" - - "2.1.1" + - "0.7.11" <- pymysql (Only for MySQL 5.7) + - "0.9.3" <- pymysql + - "1.0.2" <- pymysql (Not working, need fix) + - "2.0.1" <- mysqlclient + - "2.0.3" <- mysqlclient + - "2.1.1" <- mysqlclient - Description: The version of the python package of the connector to use. This value is used to filter tests meant for other connectors. - `python` @@ -113,11 +113,11 @@ The Makefile accept the following options - `keep_containers_alive` - Mandatory: false - Description: This option keeps all tree databases containers and the ansible-test container alive at the end of tests or in case of failure. This is useful to enter one of the containers with `podman exec -it bash` for debugging. Rerunning the -test will recreate those containers so no need to kill it. Add any value to activate this option: `keep_containers_alive=1` +tests will overwrite the 3 databases containers so no need to kill them in advance. But nothing will kill the ansible-test container. You must do that using `podman stop` and `podman rm`. Add any value to activate this option: `keep_containers_alive=1` - `continue_on_errors` - Mandatory: false - - Description: Tells ansible-test to retry on errors and also continue on errors. This is the way the GitHub Action's workflow runs the tests. This can be use to catch all errors in a single run, but you'll need to scroll up to find them. Add any value to activate this option: `continue_on_errors=1` + - Description: Tells ansible-test to retry on errors and also continue on errors. This is the way the GitHub Action's workflow runs the tests. This can be used to catch all errors in a single run, but you'll need to scroll up to find them. Add any value to activate this option: `continue_on_errors=1` #### Makefile usage examples: @@ -127,11 +127,11 @@ test will recreate those containers so no need to kill it. Add any value to acti make ansible="stable-2.12" db_engine_name="mysql" db_engine_version="5.7.40" python="3.8" connector_name="pymysql" connector_version="0.7.11" # A single target -make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="5.7.40" python="3.8" connector_name="pymysql" connector_version="0.7.11" +make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="5.7.40" python="3.8" connector_name="pymysql" connector_version="0.7.11" target="test_mysql_info" # Keep databases and ansible tests containers alives # A single target and continue on errors -make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="8.0.31" python="3.9" connector_name="mysqlclient" connector_version="2.0.3" +make ansible="stable-2.14" db_engine_name="mysql" db_engine_version="8.0.31" python="3.9" connector_name="mysqlclient" connector_version="2.0.3" target="test_mysql_query" keep_containers_alive=1 continue_on_errors=1 # If your system has an usupported version of Python: make local_python_version="3.8" ansible="stable-2.14" db_engine_name="mariadb" db_engine_version="10.6.11" python="3.9" connector_name="pymysql" connector_version="0.9.3" From a4d3246b228c0a3f76737a223e62e75620fb6a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Fri, 5 May 2023 12:42:31 +0200 Subject: [PATCH 63/63] Release 1.5.1 commit (#538) * Release 1.5.1 commit --- CHANGELOG.rst | 16 +++++++++++++++- changelogs/changelog.yaml | 15 ++++++++++++++- .../fragments/490_refactor_integration_tests.yml | 6 ------ .../fragments/backport-stable-1-pr-490.yml | 3 --- .../fragments/backport-stable-1-pr-514.yml | 3 --- galaxy.yml | 3 ++- 6 files changed, 31 insertions(+), 15 deletions(-) delete mode 100644 changelogs/fragments/490_refactor_integration_tests.yml delete mode 100644 changelogs/fragments/backport-stable-1-pr-490.yml delete mode 100644 changelogs/fragments/backport-stable-1-pr-514.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index da8e743..eac353e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,8 +5,22 @@ Community MySQL Collection Release Notes .. contents:: Topics +v1.5.1 +====== + +Release Summary +--------------- + +Final maintenance release of ``community.mysql`` major version 1. + +Major Changes +------------- + +- The ``community.mysql`` 1.x.y release stream is now effectively End of Life. No more releases will be made. This follows the decision to support each major release for two years. This decision stems from this discussion (https://github.com/ansible-collections/community.mysql/discussions/537) + + v1.5.0 -======= +====== Release Summary --------------- diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 1d4368d..09689bd 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -409,4 +409,17 @@ releases: - 1.5.0.yml - 497_mysql_info_returns_connector_name_and_version.yml - backport-stable-2-pr-452.yml - release_date: '2023-02-08' \ No newline at end of file + release_date: '2023-02-08' + 1.5.1: + changes: + major_changes: + - The ``community.mysql`` 1.x.y release stream is now effectively End of Life. + No more releases will be made. This follows the decision to support each major + release for two years. This decision stems from this + discussion (https://github.com/ansible-collections/community.mysql/discussions/537) + release_summary: Final maintenance release of ``community.mysql`` major version + 1. + fragments: + - 1.5.1.yml + - 490_refactor_integration_tests.yml + release_date: '2023-05-04' diff --git a/changelogs/fragments/490_refactor_integration_tests.yml b/changelogs/fragments/490_refactor_integration_tests.yml deleted file mode 100644 index 0762adf..0000000 --- a/changelogs/fragments/490_refactor_integration_tests.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -minor_changes: - - Integration tests - Add more versions of MariaDB - - Integration tests - Carefully verify every component of the tests in the new target 'setup_controller' to ensure expected versions are correct Python, Ansible, connector and MySQL/MariaDB. - - Integration tests - Add tools to test locally the same as on GHA by using same containers and virtualenv. Custom test containers are published in ghcr.io by this repo's workflows. MySQL/MariaDB are official Docker Hub images. - - Integration tests - New name for many tasks to makes it easier to find failing tests. Rename duplicates. Add name for tasks which doesn't had one, refactor some tests files to better group tests by subject, ... diff --git a/changelogs/fragments/backport-stable-1-pr-490.yml b/changelogs/fragments/backport-stable-1-pr-490.yml deleted file mode 100644 index 5aab754..0000000 --- a/changelogs/fragments/backport-stable-1-pr-490.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -trivial: - - Integration tests - Backport PR490 diff --git a/changelogs/fragments/backport-stable-1-pr-514.yml b/changelogs/fragments/backport-stable-1-pr-514.yml deleted file mode 100644 index b4a351e..0000000 --- a/changelogs/fragments/backport-stable-1-pr-514.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -trivial: - - Integration tests - Backport PR514 diff --git a/galaxy.yml b/galaxy.yml index 289ddf9..cd5b92f 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,6 +1,7 @@ +--- namespace: community name: mysql -version: 1.5.0 +version: 1.5.1 readme: README.md authors: - Ansible community