From 6970aef8f61373e9f85cb6f251b3b44decb7c496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Inderm=C3=BChle?= Date: Tue, 21 Mar 2023 08:16:09 +0100 Subject: [PATCH] Integrations tests : Use containers for more control and verify that versions match expectation (#490) * Draft: Add a mariadb container * Add playbook to test connection to the server * Add healthcheck to MariaDB before starting the tests This prevent the first test to fail because the db isn't ready yet. * Add default file for root necessary since using venv instead of docker * 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 ansible-test integration inventory to .gitignore * Revert to old workflow to use ansible-test --venv It seams that that ansible-test-gh-action doesn't handle this option: https://github.com/ansible-community/ansible-test-gh-action/blob/main/action.yml#L483-L497 * Cut target filtering * Fix comparison We are not logged in as 127.0.0.1 anymore, but 10.88... as I couldn't test this easily, I decided to simplify the test. * Add path to default-file /root doesn't exist with --venv * Fix workflow unknown option container_name * Attempt GHA communication between container using "docker host network" https://docs.github.com/en/actions/using-containerized-services/about-service-containers I re-revert the workflow to use the new custom action. But I'm not sure it will works because I don't know how the container for ansible-test is started and if it will have access to the services containers. * Cut anchors currently unsupported by GHA * Disable healthcheck I want to first prove that this setup is possible before adding safety * Disable sanity, units and matrix to speed up tests in GHA * Further disable tests to speed up * Add mysql_client to the controller * Install mysql_client the correct way * Fix package name and missing apt cache * 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. * Swap MariaDB with MySQL * De-duplicate the mysql_command alias * 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. * Cut docker healthcheck unsupported by GHA * Fix replication server_id already in use * Add static test with replication containers * Fix database not selected * Fix replication due to usage of gateway_addr instead of localhost * Simplify version computation * Linting * Refactor setup_mysql into setup_controller * Fix test_mysql_role * 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. * Add back a package to connect to MySQL 8+ * Linting * 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. * Fix missing var * Refactor test to use the db_version from setup_controller * Add temporary files to .gitignore * Fix volume path * Fix volume path by adding a final / * Fix volume path using $(pwd) * Fix volume path using github.workspace var * Cut files from gitignore because it prevents ansible-test to copy them * Fix pre-test-cmd missing separators * Cut the newline added by lookup 'file' * Fix tailing newline by not created it in the first place * Disable tests to concentrate on the \n and quote issue with my files * Fix trailing newline and quote in db_engine_version * Re-enable integration tests to validate db_engine_version is fixed * lint * Cut unused file * Fix pre-test-cmd paste in wrong context * Re-enable service containers * Add back docker healthcheck on services I saw in the GHA logs that it perform an healtcheck ! So I hope this will work. * Add tmate to debug the server_id in replicas * Attempt to fix "invalid syntax" * Enclose command in quotes * 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! * Re-activate all tests * Cut useless task * Use same variable as other target for consistency * Linting * Update version tested * Add options to the makefile * Add same variables as other target for consistency * Add IF NOT EXISTS to prevent misleading error on retry * Cut python 3.11 not supported by ansible-test yet * Attempt to set log-bin into docker * Reformat for readability * Document that full version is mandatory * Fix newline * Github complain it doesn't find python 3.1 !!! * Add option to run only a single target * Fix mysqlclient not supporting Python 3.9 * Enhance installation of mysql_client Initially I wanted to install mysql-client-5.7 to test mysql server 5.7 but this package is not available for Ubuntu 18+. I keep those changes because it allow us to specify the name of the package based on the Ubuntu version. * Linting * Add unique name to simplify debugging * Fix mysql_dump for MySQL 5.7 and MariaDB when using mysqldump 8 * Add unique name to simplify debugging * Deduplicate tasks * Lining * Add python script to recreate the test matrix from github workflow file * Fix dump with mysqldump 8 against mysql 5.7 * Disable test for replication with chanel for mysql 5.7 * Add better task name * Fix exclusion function * Disable replication with channel tests entirely for MySQL 5.7 * Activate Mysql 8 and Mariadb into GitHub Action Workflow * Cut Ansible since we can't change what the user have on his computer * Add running make command for all tests of the matrix * Add unique test names * Document run_all_tests.py * Add unique test names * Add tmate to experiment with docker healthcheck * 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 TODO verify that the version of mysql/mariadb is correct * Add more descriptive tests names * Use mysql_host var name instead of gateway_addr in tests * Refactor user@ into user@% * Fix healthcheck in GHA * Disable tests that fails only on MariaDB * Refactor to remove useless variables * Workaround for plugin role that fails with any MariaDB versions * Fix Python 3.10 beein run as 3.1 * Ensure replicas are healthy before rebooting them * Enable all tests * Add a virtualenv for ansible-test used locally * Simplify connector_name variables * Add PoC using custom ansible-test containers * Fix docker_container variable name * Cut forgotten comment * Fix error when using local registry by using quay.io * Change tag of test-containers to latest * Fix ansible-test unknown option I copied blindly https://github.com/ansible-collections/community.sops/blob/main/.github/workflows/ansible-test.yml#L195 and forgot what ansible-test was expecting * 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. * Add manual test matrix (MariaDB 10.6, 10.7 and 10.8 missing) * 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 * Reduce number of tests and adapt containers images * Fix queries for roles * Add filter for issues resolved in newer version of mysqlclient * Add names to tests * Fix assertion for mariadb * Linting * Cut tests for incompatible MySQL 8 and pymysql 0.7.11 * Fix assertion for older mysqlclient than 2.0.1 with mysql (mariadb ok) * Cut playbook that are now handled by the test-containers * Change timeout from 10 to 30 seconds to let mysql/mariadb restart * Add connector information to the returned values I need to know what python library was used. I had a container with both mysqlclient and pymysql installed and tests used a different connector that what is advertised by the title of integration tests. We need to prevent that otherwise our tests are worth nothing. * Add a verify stage at setup of test to assert all version are correct * Attempt to build and publish an image on ghcr.io * Add latest release of actions and with a context * Add trigger on workflow file edit * Fix env not recognized in the 'on' clause * Add latest tag * Fix insufficient context * Add missing slash * Cut addition of tag 'latest' as GHA does it automatically * Add ghcr.io image for mariadb10.3 python3.8 mysqlclient2.0.1 * Change docker-image workflow to work on all images using matrix * Fix workflow title * Add support for version of mysqlclient * Fix context path * Workaround failed to push ghcr.io Error was: failed to copy: io: read/write on closed pipe * Add back all tests using ghcr.io images * Cut unused images * Fix verify database version Sometimes, version_full contains trailing information (-log). To prevent issues it's best to concatenate major and minor version. * Fix verify for mysqlclient second name MySQLdb * Rename variable for consistency * Fix container name * Add tag 'latest' to images * Cut filter for tests now that the right connector is used * Fix test of mysql/mariadb version in use * Fix python version lookup * 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. * Document TODO * 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 dict key lookup * Fix indentation * Cut tests that was excluded in previous matrix * Enable back sanity and unit tests * Refactor get_driver_version to display name while passing sanity tests * Fix variable name * Fix missing cffi package to connect to MySQL 8 using Python 3.9 * Fix image not found * 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. * Fix verify ansible 'devel' for which the version is unknown Today 'devel' means 2.15, but in the future it will be something else. * Fix ansible version extraction for "devel" * Cut matrix from when build was done in a single workflow * Document fix container name * Add bold * Add option to let containers alive at end of testing * Enhance error handling and doc of get_driver_name and get_driver_version * Migrate tests documentations in their own file * Skip retry-on-error by default and add option to activate it on demand * Rename folder to better purpose * Enable back push and schedule workflow * Rename registry from fork to upstream * Cut Docker Image workflow's filter for branch from my fork * Add changelog fragment * Update supported versions * Rename file for clarity * Cut mariadb non long term releases * Add '-client' to the block title to better explain what it is * Update readme for tested versions of long term release of MariaDB * Attempt to add the workflow to the Action tab * Second attempt to add the workflow to the Action tab * Cut folder re-created by merge from main * Cut filter by branch GHA will build the image using the branch name as tag. So we can safely remove this filter. * Cut changelog item done in #497 * Attempt to fix upload of image under c.mysql instead of my fork * Add debug to buildkitd * Bump setup-buildy-action to latest * Cut dot in image name in attempt to fix buildx bad request 400 error * Sanitize the repository name using metadata-action https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md#repository-name-must-be-lowercase * Document why we use optional checkout action * Cut debugging from setup-buildx-action * Fix workflow to work both on fork and c.mysql repository * Use apt-get instead of apt that not have a stable CLI interface * Use apt-get instead of apt * update docker image path to my personal repo I'm unable to publish under community.mysql. Either it's the dot in the name or I do something wrong with the GITHUB_TOKEN, but we need to test my PR, so I'll use docker images from my fork for now. * Fix test after merge of PR497 * Enhance testing documentation header * Fix installation of ansible venv ansible-test is included in ansible package. Also, on Fedora 37 with python 3.11, pip is missing. By using ensurepip we solve that issue. * Document usage of continue_on_errors * Fix versions used in examples * Add support for systems with unsupported python set as default * Fix cleanup task * Fix variable assignation to the include task * Add forgotten variable to handle unsupported python version * Fix user site-packages not visible in virtualenv * Fix test connection to the database and tasks names * 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 * Reformat command multiline to oneline * Add deletion of anonymous volumes associated with the container * Comment unused variable * 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 spelling Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Reformat file path Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Fix link URI Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Fix link URI Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Lint Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Lint Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Add better task name Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) * Move utility task files in their own folder * Refactor using reusable GHA workflows * Fix path to called workflow file * Fix path to use local workflow * Fix cannot specify version when calling local workflows * Attempt to use a fixed repo name in the image name My last attempts produced duplicates images under my name + repo name: laurent-indermuehle/community.mysql. Previously I had only my name. And none of the above are what we want. We want only community.mysql in the image name... * 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-collection. 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) --- .github/workflows/ansible-test-plugins.yml | 379 ++++- .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 + 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 | 8 - .../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 | 21 - .../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 | 54 +- .../targets/test_mysql_db/tasks/issue-28.yml | 16 +- .../tasks/issue_256_mysqldump_errors.yml | 3 +- .../targets/test_mysql_db/tasks/main.yml | 5 +- .../tasks/multi_db_create_delete.yml | 45 +- .../test_mysql_db/tasks/state_dump_import.yml | 219 ++- .../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 | 32 +- .../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 | 177 +- .../tasks/mysql_replication_primary_delay.yml | 2 +- .../mysql_replication_resetprimary_mode.yml | 2 +- .../targets/test_mysql_role/defaults/main.yml | 17 +- .../targets/test_mysql_role/meta/main.yml | 3 +- .../targets/test_mysql_role/tasks/main.yml | 11 +- .../tasks/mysql_role_initial.yml | 1497 +++++++++-------- .../tasks/test_priv_subtract.yml | 32 +- .../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 | 46 - .../test_mysql_user/tasks/issue-121.yml | 48 +- .../test_mysql_user/tasks/issue-265.yml | 71 +- .../test_mysql_user/tasks/issue-28.yml | 51 +- .../test_mysql_user/tasks/issue-29511.yaml | 30 +- .../test_mysql_user/tasks/issue-64560.yaml | 19 +- .../targets/test_mysql_user/tasks/main.yml | 152 +- .../test_mysql_user/tasks/remove_user.yml | 74 - .../tasks/test_idempotency.yml | 84 + .../tasks/test_priv_append.yml | 57 +- .../test_mysql_user/tasks/test_priv_dict.yml | 80 +- .../tasks/test_priv_subtract.yml | 76 +- .../test_mysql_user/tasks/test_privs.yml | 102 +- .../tasks/test_privs_issue_465.yml | 6 +- ...ce_limits.yml => test_resource_limits.yml} | 54 +- ...y_grant.yml => test_revoke_only_grant.yml} | 30 +- ...irements.yml => test_tls_requirements.yml} | 98 +- .../tasks/test_update_password.yml | 15 +- .../test_user_grants_with_roles_applied.yml | 51 +- .../tasks/test_user_password.yml | 110 +- .../tasks/test_user_plugin_auth.yml | 249 +-- .../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 + 126 files changed, 3586 insertions(+), 2466 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 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 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 delete mode 100644 tests/integration/targets/test_mysql_user/tasks/create_user.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 rename tests/integration/targets/test_mysql_user/tasks/{resource_limits.yml => test_resource_limits.yml} (60%) rename tests/integration/targets/test_mysql_user/tasks/{revoke_only_grant.yml => test_revoke_only_grant.yml} (61%) 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/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 ea6ae8ef..5aeee56e 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,47 +40,312 @@ jobs: strategy: fail-fast: false matrix: - db_engine_version: - - mysql_5.7.31 - - mysql_8.0.22 - - mariadb_10.3.34 - - mariadb_10.8.3 - 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 - - db_engine_version: mariadb_10.8.3 - 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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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/laurent-indermuehle/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 }} @@ -92,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 @@ -126,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 4748b5ad..13e7d417 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 00000000..fa10268b --- /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 00000000..3d902700 --- /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 00000000..1ca4600d --- /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 00000000..37e91ee1 --- /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 00000000..30acfc12 --- /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 00000000..0fa7403f --- /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 00000000..adfe9e37 --- /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 00000000..2c18f635 --- /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 00000000..1568d223 --- /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 00000000..39bb583d --- /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 00000000..824f77c4 --- /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 00000000..0c54e126 --- /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 00000000..0ac76b2c --- /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 00000000..1677be69 --- /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 00000000..e6b41db1 --- /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 00000000..72ffd602 --- /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 1922df0f..9555f5e6 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 00000000..a94ffd8e --- /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 5f952518..07c32145 100644 --- a/README.md +++ b/README.md @@ -63,23 +63,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 00000000..9aad0f56 --- /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 00000000..0762adfe --- /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/run_all_tests.py b/run_all_tests.py new file mode 100755 index 00000000..b7779a5c --- /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 00000000..68ea3f68 --- /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 00000000..22c8c577 --- /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 00000000..b7837b2a --- /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 00000000..a1451ff1 --- /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 00000000..f7e9eb18 --- /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 00000000..afe6a77c --- /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 00000000..0eb17782 --- /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 00000000..9141709d --- /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 00000000..6b0f519a --- /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 00000000..1aea0cd1 --- /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 00000000..871a1e4f --- /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 00000000..eb835c21 --- /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 00000000..e97e5e26 --- /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 00000000..396d8957 --- /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 00000000..57ef15e1 --- /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 3751f4ef..eb32dc1a 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 e3e76058..699b61f8 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 98fa5fe6..3928c78c 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 86a67606..f65d0902 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 00000000..49531b8d --- /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 00000000..0d5e36bb --- /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 00000000..d74136da --- /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 00000000..74aa0f26 --- /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 cceb8f54..00000000 --- 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 8f751ee4..00000000 --- a/tests/integration/targets/setup_mysql/handlers/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: "{{ role_name }} | handler | create dbdeployer installed file" - template: - src: installed_file.j2 - dest: "{{ dbdeployer_installed_file }}" - listen: create zookeeper installed file - tags: - - setup_mysql 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 2b27e273..00000000 --- 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 dc028799..00000000 --- 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 b64af25d..00000000 --- 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 47a5ee00..00000000 --- a/tests/integration/targets/setup_mysql/tasks/main.yml +++ /dev/null @@ -1,21 +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 - tags: - - setup_mysql -- import_tasks: dir.yml - tags: - - setup_mysql -- import_tasks: install.yml - tags: - - setup_mysql -- import_tasks: config.yml - tags: - - setup_mysql -- import_tasks: verify.yml - tags: - - setup_mysql 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 cfc90c1b..00000000 --- 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 ca383d98..00000000 --- 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 862a357a..00000000 --- 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 8fbcd905..00000000 --- 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 6448e156..30ac858c 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 f1174ff2..aebda436 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 c2fda2ad..390c6ae7 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 9ef3af57..02e5df2c 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 - -- name: check encoding of table - shell: "{{ mysql_command }} {{ db_latin1_name }} -e \"SHOW FULL COLUMNS FROM testlatin1\"" + - result is changed + +- 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 64fe9d5b..8cad28e6 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: @@ -25,6 +25,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -32,6 +33,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' tls_requires: @@ -43,7 +45,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 @@ -52,12 +54,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: @@ -65,7 +69,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 @@ -80,5 +84,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 index 58285b32..ea1768ad 100644 --- 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 @@ -7,7 +7,7 @@ community.mysql.mysql_db: &mysql_defaults login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' community.mysql.mysql_query: *mysql_defaults @@ -73,6 +73,7 @@ name: all target: /tmp/full-dump-without-t1.sql pipefail: true # This should do nothing + register: full_dump_without_t1 ignore_errors: true diff --git a/tests/integration/targets/test_mysql_db/tasks/main.yml b/tests/integration/targets/test_mysql_db/tasks/main.yml index df6bb077..544ad4d6 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 c2eb13c4..0bd7d587 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 724dd186..b4f9cda9 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 @@ -419,22 +422,22 @@ ######################## # Test import with chdir -- name: Create dir +- name: Dump and Import | Create dir file: path: ~/subdir state: directory -- name: Create test dump +- name: Dump and Import | Create test dump shell: 'echo "SOURCE ./subdir_test.sql" > ~/original_test.sql' -- name: Create test source +- name: Dump and Import | Create test source shell: 'echo "SELECT 1" > ~/subdir/subdir_test.sql' -- name: Try to restore without chdir argument, must fail +- name: Dump and Import | Try to restore without chdir argument, 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 @@ -443,14 +446,14 @@ register: result - assert: that: - - result is failed - - result.msg is search('Failed to open file') + - result is failed + - result.msg is search('Failed to open file') -- name: Restore with chdir argument, must pass +- name: Dump and Import | Restore with chdir argument, must pass 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 @@ -459,46 +462,30 @@ register: result - assert: that: - - result is succeeded + - result is succeeded ########## # 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 5b6e871d..12633f2a 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 e1b932cc..e1cd8800 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 a7ace5d1..4be5f587 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 ba76f59b..d525e8e9 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 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 bf4576f5..83e6883f 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: @@ -29,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -36,6 +34,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" tls_requires: SSL: @@ -45,7 +44,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 @@ -54,19 +53,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 @@ -81,5 +82,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 a5428e32..a01f9153 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 4ee25ffe..6befdcf5 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 ce08dc4a..01ee3db7 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 a61e07ff..e788feaf 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: @@ -29,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -36,6 +34,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "%" password: "{{ user_password_1 }}" tls_requires: SSL: @@ -45,7 +44,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 @@ -54,19 +53,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 @@ -81,5 +82,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 cbb7b533..d97c5544 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 d2d20808..48fd5602 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 36e111c3..01ee3db7 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 index 24232f35..1718b998 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/issue-265.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/issue-265.yml @@ -1,13 +1,10 @@ --- -- name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --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: @@ -29,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host: '{{ gateway_addr }}' state: absent ignore_errors: yes @@ -38,6 +36,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: '{{ gateway_addr }}' password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' force_context: yes @@ -47,7 +46,7 @@ mode: getprimary login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_replica1_port }}' register: result ignore_errors: yes @@ -60,6 +59,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host: '{{ gateway_addr }}' state: absent force_context: yes @@ -68,7 +68,7 @@ mode: getprimary login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_replica1_port }}' register: result ignore_errors: yes @@ -92,12 +92,12 @@ - result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"] - name: Create replication filter MySQL - shell: "echo \"CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = (mysql);\" | {{ mysql_command }} -P{{ mysql_replica1_port }}" - when: install_type == 'mysql' + shell: "echo \"CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = (mysql);\" | {{ mysql_command_wo_port }} -P{{ mysql_replica1_port }}" + when: db_engine == 'mysql' - name: Create replication filter MariaDB - shell: "echo \"SET GLOBAL replicate_ignore_db = 'mysql';\" | {{ mysql_command }} -P{{ mysql_replica1_port }}" - when: install_type == 'mariadb' + shell: "echo \"SET GLOBAL replicate_ignore_db = 'mysql';\" | {{ mysql_command_wo_port }} -P{{ mysql_replica1_port }}" + when: db_engine == 'mariadb' - name: Start replica mysql_replication: @@ -117,6 +117,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: "{{ gateway_addr }}" password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' force_context: yes @@ -126,7 +127,7 @@ mode: getprimary login_user: '{{ user_name_1 }}' login_password: '{{ user_password_1 }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_replica1_port }}' register: result ignore_errors: yes @@ -139,6 +140,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host: "{{ gateway_addr }}" state: absent force_context: yes @@ -157,9 +159,9 @@ - result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"] - name: Remove replication filter MySQL - shell: "echo \"CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = ();\" | {{ mysql_command }} -P{{ mysql_replica1_port }}" - when: install_type == 'mysql' + shell: "echo \"CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = ();\" | {{ mysql_command_wo_port }} -P{{ mysql_replica1_port }}" + when: db_engine == 'mysql' - name: Remove replication filter MariaDB - shell: "echo \"SET GLOBAL replicate_ignore_db = '';\" | {{ mysql_command }} -P{{ mysql_replica1_port }}" - when: install_type == 'mariadb' + shell: "echo \"SET GLOBAL replicate_ignore_db = '';\" | {{ mysql_command_wo_port }} -P{{ mysql_replica1_port }}" + when: db_engine == 'mariadb' 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 e6333f0a..4225a076 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: @@ -29,6 +26,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -46,7 +44,7 @@ mode: getprimary 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 +53,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: getprimary 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 +82,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 044787ab..15749210 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/main.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/main.yml @@ -18,7 +18,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 resetprimary mode: - import_tasks: mysql_replication_resetprimary_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 e314aaeb..f438dbf0 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 primary 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 78206fc8..1dd4c88a 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' - - - name: alias mysql command to include default options - set_fact: - mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --protocol=tcp" - - # Preparation: + - db_engine == 'mysql' + - db_version is version('8.0.22', '>=') + + # 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 getprimary mode: - name: Get primary status @@ -63,11 +85,12 @@ mode: getprimary register: mysql_primary_status - - assert: + - name: Assert that primary is in expected state + assert: that: - - mysql_primary_status.Is_Primary == true - - mysql_primary_status.Position != 0 - - mysql_primary_status is not changed + - mysql_primary_status.Is_Primary == true + - mysql_primary_status.Position != 0 + - mysql_primary_status is not changed # Test startreplica fails without changeprimary first. This needs fail_on_error - name: Start replica and fail because primary is not specified; failing on error as requested @@ -80,9 +103,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 @@ -93,9 +117,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. @@ -106,9 +131,10 @@ mode: startreplica register: result - - assert: + - name: Assert that start replica succeeded again + assert: that: - - result is not failed + - result is not failed # Test changeprimary mode: # primary_ssl_ca will be set as '' to check the module's behaviour for #23976, @@ -128,10 +154,11 @@ primary_ssl: no 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=0,MASTER_SSL_CA=''"] + - 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=0,MASTER_SSL_CA=''"] # Test startreplica mode: - name: Start replica @@ -141,10 +168,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 @@ -154,34 +182,36 @@ mode: getreplica 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_Replica == true - - replica_status.Master_Host == '{{ mysql_host }}' - - replica_status.Exec_Master_Log_Pos == mysql_primary_status.Position - - replica_status.Master_Port == {{ mysql_primary_port }} - - replica_status.Last_IO_Errno == 0 - - replica_status.Last_IO_Error == '' - - replica_status is not changed + - replica_status.Is_Replica == true + - replica_status.Master_Host == '{{ mysql_host }}' + - replica_status.Exec_Master_Log_Pos == mysql_primary_status.Position + - replica_status.Master_Port == {{ mysql_primary_port }} + - replica_status.Last_IO_Errno == 0 + - replica_status.Last_IO_Error == '' + - 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_Replica == true - - replica_status.Source_Host == '{{ mysql_host }}' - - replica_status.Exec_Source_Log_Pos == mysql_primary_status.Position - - replica_status.Source_Port == {{ mysql_primary_port }} - - replica_status.Last_IO_Errno == 0 - - replica_status.Last_IO_Error == '' - - replica_status is not changed + - replica_status.Is_Replica == true + - replica_status.Source_Host == '{{ mysql_host }}' + - replica_status.Exec_Source_Log_Pos == mysql_primary_status.Position + - replica_status.Source_Port == {{ mysql_primary_port }} + - replica_status.Last_IO_Errno == 0 + - replica_status.Last_IO_Error == '' + - replica_status is not changed when: mysql8022_and_higher == true # 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: @@ -197,19 +227,18 @@ # 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 - - shell: pip show pymysql | awk '/Version/ {print $2}' - register: pymysql_version - - name: Start replica that is already running mysql_replication: <<: *mysql_params @@ -219,7 +248,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: @@ -233,10 +263,11 @@ mode: stopreplica 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: @@ -252,7 +283,8 @@ fail_on_error: true register: result - - assert: + - name: Assert that stopreplica is not changed + assert: that: - result is not changed when: @@ -269,7 +301,8 @@ register: result ignore_errors: yes - - assert: + - name: Assert that stopslave returns expected error message + assert: that: - - result.msg == "value of mode must be one of{{ ":" }} getprimary, getreplica, changeprimary, stopreplica, startreplica, resetprimary, resetreplica, resetreplicaall, got{{ ":" }} stopslave" - - result is failed + - result.msg == "value of mode must be one of{{ ":" }} getprimary, getreplica, changeprimary, stopreplica, startreplica, resetprimary, resetreplica, resetreplicaall, got{{ ":" }} stopslave" + - result is failed diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_primary_delay.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_primary_delay.yml index ecdcc816..5e967e82 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_primary_delay.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_primary_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_resetprimary_mode.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetprimary_mode.yml index a4ed75e1..4bccc76b 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetprimary_mode.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_resetprimary_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_role/defaults/main.yml b/tests/integration/targets/test_mysql_role/defaults/main.yml index 544f0983..62dc5f1f 100644 --- a/tests/integration/targets/test_mysql_role/defaults/main.yml +++ b/tests/integration/targets/test_mysql_role/defaults/main.yml @@ -1,18 +1,5 @@ +--- mysql_user: root mysql_password: msandbox +mysql_host: '{{ gateway_addr }}' mysql_primary_port: 3307 - -test_db: test_db -test_table: test_table -test_db1: test_db1 -test_db2: test_db2 - -user0: user0 -user1: user1 -user2: user2 -nonexistent: user3 - -role0: role0 -role1: role1 -role2: role2 -role3: role3 \ No newline at end of file diff --git a/tests/integration/targets/test_mysql_role/meta/main.yml b/tests/integration/targets/test_mysql_role/meta/main.yml index ce08dc4a..01ee3db7 100644 --- a/tests/integration/targets/test_mysql_role/meta/main.yml +++ b/tests/integration/targets/test_mysql_role/meta/main.yml @@ -1,2 +1,3 @@ +--- dependencies: -- setup_mysql + - setup_controller diff --git a/tests/integration/targets/test_mysql_role/tasks/main.yml b/tests/integration/targets/test_mysql_role/tasks/main.yml index 952bf6f0..c3c9bd37 100644 --- a/tests/integration/targets/test_mysql_role/tasks/main.yml +++ b/tests/integration/targets/test_mysql_role/tasks/main.yml @@ -3,13 +3,12 @@ # and should not be used as examples of how to write Ansible roles # #################################################################### -- 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" - - # mysql_role module initial CI tests -- import_tasks: mysql_role_initial.yml +# TODO, many tests fails with MariaDB, debug them then remove the +# when clause and swap include_tasks for import_tasks. +- include_tasks: mysql_role_initial.yml + when: + - db_engine == 'mysql' # Test that subtract_privs will only revoke the grants given by priv # (https://github.com/ansible-collections/community.mysql/issues/331) diff --git a/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml b/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml index 36f2418a..3762df96 100644 --- a/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml +++ b/tests/integration/targets/test_mysql_role/tasks/mysql_role_initial.yml @@ -1,15 +1,13 @@ +--- # Test code for mysql_role module - 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 }}' - task_parameters: &task_params - register: result - block: - name: Get server version @@ -18,1323 +16,1338 @@ register: srv - name: When run with unsupported server versions, must fail - <<: *task_params mysql_role: <<: *mysql_params name: test + register: result ignore_errors: yes - name: Must fail when meet unsupported version assert: that: - - result is failed - - result is search('Roles are not supported by the server') + - result is failed + - result is search('Roles are not supported by the server') when: - - srv['version']['major'] < 8 + - srv['version']['major'] < 8 - # Skip unsupported versions - - meta: end_play + - name: Skip unsupported versions + meta: end_play when: srv['version']['major'] < 8 ######### # Prepare - - name: Create db {{ test_db }} - <<: *task_params + - name: Create db test_db mysql_db: <<: *mysql_params - name: '{{ test_db }}' + name: 'test_db' + register: result - - name: Create table {{ test_table }} - <<: *task_params + - name: Create table test_table mysql_query: <<: *mysql_params - login_db: '{{ test_db }}' - query: 'DROP TABLE IF EXISTS {{ test_table }}' + login_db: 'test_db' + query: 'DROP TABLE IF EXISTS test_table' + register: result - - name: Create table {{ test_table }} - <<: *task_params + - name: Create table test_table mysql_query: <<: *mysql_params - login_db: '{{ test_db }}' - query: 'CREATE TABLE IF NOT EXISTS {{ test_table }} (id int)' + login_db: 'test_db' + query: 'CREATE TABLE IF NOT EXISTS test_table (id int)' + register: result - name: Create users - <<: *task_params mysql_user: <<: *mysql_params name: '{{ item }}' + host: '%' password: '{{ mysql_password }}' loop: - - '{{ user0 }}' - - '{{ user1 }}' - - '{{ user2 }}' + - 'user0' + - 'user1' + - 'user2' ########### # Run tests - - name: Create role {{ role0 }} in check_mode - <<: *task_params + - name: Create role0 in check_mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result check_mode: yes - - name: Check + - name: Assert that create role0 is changed assert: that: - - result is changed + - result is changed - name: Check in DB - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that user is not in mysql.user assert: that: - - result.rowcount.0 == 0 + - result.rowcount.0 == 0 # It must fail because of check_mode - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Check in DB, if not granted, the query will fail (expect failure) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that show grants is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - name: Check in DB (mariadb) - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that user is not in mysql.roles_mapping (mariadb) assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - #===================== + # ===================== - name: Check that the user have no active roles - <<: *task_params mysql_query: - login_user: '{{ user0 }}' + login_user: 'user0' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' query: 'SELECT COALESCE(current_role(), "NONE") as "current_role()"' + register: result - - name: Check + - name: Assert that the user have no active roles assert: that: - - result.query_result.0.0["current_role()"] == "NONE" + - result.query_result.0.0["current_role()"] == "NONE" - - name: Create role {{ role0 }} - <<: *task_params + - name: Create role role0 mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result - - name: Check + - name: Assert that create role is changed assert: that: - - result is changed + - result is changed - name: Check in DB - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 is in mysql.user assert: that: - - result.rowcount.0 == 1 + - result.rowcount.0 == 1 - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query role0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that show grants is succeeded (mysql) assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - name: Check in DB (mariadb) - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that role is in mysql.roles_mapping (mariadb) assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - name: Check that the role is active - <<: *task_params mysql_query: - login_user: '{{ user0 }}' + login_user: 'user0' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' query: 'SELECT current_role()' - when: install_type == 'mysql' + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that current_role() returns role0 assert: that: - - "'{{ role0 }}' in result.query_result.0.0['current_role()']" - when: install_type == 'mysql' + - "'role0' in result.query_result.0.0['current_role()']" + when: db_engine == 'mysql' - name: Check that the role is active (mariadb) - <<: *task_params mysql_query: - login_user: '{{ user0 }}' + login_user: 'user0' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' query: - - 'SET ROLE {{ role0 }}' + - 'SET ROLE role0' - 'SELECT current_role()' - when: install_type == 'mariadb' + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that role is active (mariadb) assert: that: - - "'{{ role0 }}' in result.query_result.1.0['current_role()']" - when: install_type == 'mariadb' + - "'role0' in result.query_result.1.0['current_role()']" + when: db_engine == 'mariadb' - #======================== + # ======================== - - name: Create role {{ role0 }} again in check_mode - <<: *task_params + - name: Create role role0 again in check_mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present + register: result check_mode: yes - - name: Check + - name: Assert that create role role0 again is not changed assert: that: - - result is not changed + - result is not changed - name: Check in DB - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role role0 is present in the database assert: that: - - result.rowcount.0 == 1 + - result.rowcount.0 == 1 - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query role0, if not granted, the query will fail (2) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query for the role0 is succeeded for mysql (2) assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - name: Check in DB (mariadb) - <<: *task_params mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query for the role0 is succeeded for mariadb assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - #======================== + # ======================== - - name: Create role {{ role0 }} again - <<: *task_params + - name: Create role0 again mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present + register: result - - name: Check + - name: Assert that create role0 again is not changed assert: that: - - result is not changed + - result is not changed - - name: Check in DB - <<: *task_params + - name: Query role0 mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 is in DB assert: that: - - result.rowcount.0 == 1 + - result.rowcount.0 == 1 - #======================== + # ======================== - - name: Drop role {{ role0 }} in check_mode - <<: *task_params + - name: Drop role0 in check_mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: absent + register: result check_mode: yes - - name: Check + - name: Assert that drop role0 in check_mode is changed assert: that: - - result is changed + - result is changed - - name: Check in DB - <<: *task_params + - name: Query role0 mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 is in DB assert: that: - - result.rowcount.0 == 1 + - result.rowcount.0 == 1 # Must pass because of check_mode - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query role0, if not granted, the query will fail (3) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that role0 is still in mysql after drop in check_mode (3) assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' # Must pass because of check_mode - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that role0 is still in mariadb after drop in check_mode assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - #======================== + # ======================== - - name: Drop role {{ role0 }} - <<: *task_params + - name: Drop role0 mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: absent + register: result - - name: Check + - name: Assert that drop role0 is changed assert: that: - - result is changed + - result is changed - - name: Check in DB - <<: *task_params + - name: Query role0 mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 is absent from db assert: that: - - result.rowcount.0 == 0 + - result.rowcount.0 == 0 - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query grants for role0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query for role0 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 in mariadb mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result ignore_errors: yes - when: install_type == 'mariadb' + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user0 and role0 in mariadb returns 0 rows assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - #======================== + # ======================== - - name: Drop role {{ role0 }} again in check_mode - <<: *task_params + - name: Drop role0 again in check_mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: absent + register: result check_mode: yes - - name: Check + - name: Assert that drop role0 again in check_mode is not changed assert: that: - - result is not changed + - result is not changed - - name: Drop role {{ role0 }} again - <<: *task_params + - name: Drop role0 again mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: absent + register: result - - name: Check + - name: Assert that drop role0 again is not changed assert: that: - - result is not changed + - result is not changed # ================== - - name: Create role {{ role0 }} in check_mode - <<: *task_params + - name: Create role0 in check_mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' priv: '*.*': 'SELECT,INSERT' 'mysql.*': 'UPDATE' + register: result check_mode: yes - - name: Check + - name: Assert that create role0 in check_mode is changed assert: that: - - result is changed + - result is changed - - name: Check in DB - <<: *task_params + - name: Query role0 mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 created in check_mode is not in the database assert: that: - - result.rowcount.0 == 0 + - result.rowcount.0 == 0 - #======================== + # ======================== - - name: Create role {{ role0 }} - <<: *task_params + - name: Create role0 mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' priv: '*.*': 'SELECT,INSERT' 'mysql.*': 'UPDATE' + register: result - - name: Check + - name: Assert that create role0 is changed assert: that: - - result is changed + - result is changed - - name: Check in DB - <<: *task_params + - name: Query role0 mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}'" + query: "SELECT 1 FROM mysql.user WHERE User = 'role0'" + register: result - - name: Check + - name: Assert that role0 is in the database assert: that: - - result.rowcount.0 == 1 + - result.rowcount.0 == 1 - #======================== + # ======================== - - name: Create role {{ role0 }} in check_mode again - <<: *task_params + - name: Create role0 in check_mode again mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' priv: '*.*': 'SELECT,INSERT' 'mysql.*': 'UPDATE' + register: result check_mode: yes - - name: Check + # TODO fix this with mariadb. I disable this test because I'm not an + # expert with roles and I don't know if it's a correct behavior of our module + # against MariaDB or if it is a bug. We never tested MariaDB properly... + - name: Assert that create role0 in check_mode again is not changed assert: that: - - result is not changed + - result is not changed + when: + - db_engine == 'mysql' - #======================== + # ======================== - - name: Create role {{ role0 }} again - <<: *task_params + - name: Create role0 again (2) mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user0 }}@localhost' + - 'user0@%' priv: '*.*': 'SELECT,INSERT' 'mysql.*': 'UPDATE' + register: result - - name: Check + # TODO fix this with mariadb. I disable this test because I'm not an + # expert with roles and I don't know if it's a correct behavior of our module + # against MariaDB or if it is a bug. We never tested MariaDB properly... + - name: Assert that create role0 again is not changed (2) assert: that: - - result is not changed + - result is not changed + when: + - db_engine == 'mysql' + # ############################################## # Test rewriting / appending / detaching members # ############################################## - - name: Create role {{ role1 }} - <<: *task_params + - name: Create role1 mysql_role: <<: *mysql_params - name: '{{ role1 }}' + name: 'role1' state: present + register: result # Rewriting members - name: Rewrite members in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' - - '{{ role1 }}' + - 'user1@%' + - 'user2@%' + - 'role1' + register: result check_mode: yes - - name: Check + - name: Assert that rewrite members in check_mode is changed assert: that: - - result is changed + - result is changed # user0 is still a member because of check_mode - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that show grants for user0 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' # user0 is still a member because of check_mode - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that show grants for user0 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' # user1, user2, and role1 are not members because of check_mode - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user1, if not granted, the query will fail (expect failue) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user1@'%' USING 'role0'" ignore_errors: yes - when: install_type == 'mysql' + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query for user1 in mysql is failed due to check_mode assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user1 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user1 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user1' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query for user1 in mariadb is failed due to check_mode assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user2, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user2 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user2@'%' USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query for user2 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user2 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user2 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user2' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query user2 in mariadb returns 0 row assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query role1, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role1 }} USING '{{ role0 }}'" + query: "SHOW GRANTS FOR role1 USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query role1 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query role1 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ role1 }}' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'role1' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query role0 in mariadb returns 0 row assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - #======================== + # ======================== - name: Rewrite members - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' - - '{{ role1 }}' + - 'user1@%' + - 'user2@%' + - 'role1' + register: result - - name: Check + - name: Assert that rewrite members is changed assert: that: - - result is changed + - result is changed # user0 is not a member any more - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user0 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' # user0 is not a member any more - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user0 (mariadb) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost" - when: install_type == 'mariadb' + query: "SHOW GRANTS FOR user0@'%'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query user0 in mariadb doesn't returns role0 assert: that: - - "'{{ role0 }}' not in result.query_result.0.0['Grants for user0@localhost']" - when: install_type == 'mariadb' + - "'role0' not in result.query_result.0.0['Grants for user0@%']" + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user1, if not granted, the query will fail (expect success) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user1@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user1 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user1 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user1 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user1' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query user1 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user2, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user2 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user2@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user2 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query user2 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user2 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user2' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query user2 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query role0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role1 }} USING '{{ role0 }}'" + query: "SHOW GRANTS FOR role1 USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query role0 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count user is role1 and role is role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ role1 }}' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'role1' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count user is role1 and role is role0 returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - #========================== + # ========================== - name: Rewrite members again in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' - - '{{ role1 }}' + - 'user1@%' + - 'user2@%' + - 'role1' + register: result check_mode: yes - - name: Check + - name: Assert that rewrite members again in check_mode is not changed assert: that: - - result is not changed + - result is not changed - #========================== + # ========================== - name: Rewrite members again - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' - - '{{ role1 }}' + - 'user1@%' + - 'user2@%' + - 'role1' + register: result - - name: Check + - name: Assert that rewrite members again is not changed assert: that: - - result is not changed + - result is not changed - #========================== + # ========================== # Append members - name: Append a member in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present append_members: yes members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result check_mode: yes - - name: Check + - name: Assert that append a member in check_mode is changed assert: that: - - result is changed + - result is changed - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail (expect failure) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" ignore_errors: yes - when: install_type == 'mysql' + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user0 is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user0 and role0 in mariadb resturns 0 row assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' - #===================== + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' + # ===================== - name: Append a member - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present append_members: yes members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result - - name: Check + - name: Assert that append a member is changed assert: that: - - result is changed + - result is changed - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user0 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user0 and role0 in mariadb resturns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' # user1 and user2 must still be in DB because we are appending - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user1 using role0 (expect success) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user1@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query for user1 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user1 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user1 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user1' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user1 and role0 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user2, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user2 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user2@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user2 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user2 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user2 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user2' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user2 and role0 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - #======================== + # ======================== - name: Append a member again in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present append_members: yes members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result check_mode: yes - - name: Check + - name: Assert that append a member again in check_mode is not changed assert: that: - - result is not changed + - result is not changed - #======================== + # ======================== - name: Append a member again - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present append_members: yes members: - - '{{ user0 }}@localhost' + - 'user0@%' + register: result - - name: Check + - name: Assert that append a member again is not changed assert: that: - - result is not changed + - result is not changed ############## # Detach users - name: Detach users in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present detach_members: yes members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' + - 'user1@%' + - 'user2@%' + register: result check_mode: yes - - name: Check + - name: Assert that detach users in check_mode is changed assert: that: - - result is changed + - result is changed # They must be there because of check_mode - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user0 is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user0 and role0 in mariadb resturns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user1 using role0 (expect success) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user1@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user1 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user1 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user1 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user1' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user1 and role0 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user2, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user2 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user2@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user2 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count user2 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user2 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user2' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count user2 and role0 in mariadb returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - #======================== + # ======================== - name: Detach users - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present detach_members: yes members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' + - 'user1@%' + - 'user2@%' + register: result - - name: Check + - name: Assert that detach users is changed assert: that: - - result is changed + - result is changed - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user0, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user0 }}@localhost USING '{{ role0 }}'" - when: install_type == 'mysql' + query: "SHOW GRANTS FOR user0@'%' USING 'role0'" + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user0 in mysql is succeeded assert: that: - - result is succeeded - when: install_type == 'mysql' + - result is succeeded + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user0 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user0 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user0' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user0 and role0 returns 1 row assert: that: - - result.query_result.0.0['user_roles'] == 1 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 1 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user1, if not granted, the query will fail (expect failure) mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user1@'%' USING 'role0'" ignore_errors: yes - when: install_type == 'mysql' + register: result + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user1 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user1 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user1 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user1' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user1 and role0 in mariadb returns 0 row assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - - name: Check in DB, if not granted, the query will fail - <<: *task_params + - name: Query user2, if not granted, the query will fail mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user2 }}@localhost USING '{{ role0 }}'" + query: "SHOW GRANTS FOR user2@'%' USING 'role0'" + register: result ignore_errors: yes - when: install_type == 'mysql' + when: db_engine == 'mysql' - - name: Check + - name: Assert that query user2 in mysql is failed assert: that: - - result is failed - when: install_type == 'mysql' + - result is failed + when: db_engine == 'mysql' - - name: Check in DB (mariadb) - <<: *task_params + - name: Query count for user2 and role0 (mariadb) mysql_query: <<: *mysql_params - query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = '{{ user2 }}' AND Host = 'localhost' AND Role = '{{ role0 }}'" - when: install_type == 'mariadb' + query: "SELECT count(User) as user_roles FROM mysql.roles_mapping WHERE User = 'user2' AND Host = '%' AND Role = 'role0'" + register: result + when: db_engine == 'mariadb' - - name: Check (mariadb) + - name: Assert that query count for user2 and role0 returns 0 row assert: that: - - result.query_result.0.0['user_roles'] == 0 - when: install_type == 'mariadb' + - result.query_result.0.0['user_roles'] == 0 + when: db_engine == 'mariadb' - #===================== + # ===================== - name: Detach users in check_mode again - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present detach_members: yes members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' + - 'user1@%' + - 'user2@%' + register: result check_mode: yes - - name: Check + - name: Assert that detach users in check_mode again is not changed assert: that: - - result is not changed + - result is not changed - name: Detach users again - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present detach_members: yes members: - - '{{ user1 }}@localhost' - - '{{ user2 }}@localhost' + - 'user1@%' + - 'user2@%' + register: result - - name: Check + - name: Assert that detach users again is not changed assert: that: - - result is not changed + - result is not changed - name: '"detach" users when creating a new role' - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role3 }}' + name: 'role3' state: present detach_members: yes members: - - '{{ user1 }}@localhost' + - 'user1@%' + register: result - - name: Check the role was created + - name: Assert that creating a role while detach users is changed assert: that: - result is changed - - name: Check grants - <<: *task_params + - name: Query grants for user1 mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ user1 }}@localhost" + query: "SHOW GRANTS FOR user1@'%'" + register: result - - name: asssert detach_members did not add a user to the role + - name: Assert detach_members did not add a user to the role assert: that: - - "'{{ role3 }}' not in result.query_result.0.0['Grants for {{ user1 }}@localhost']" + - "'role3' not in result.query_result.0.0" # test members_must_exist - - name: try failing on not-existing user in check-mode - <<: *task_params + - name: Try failing on not-existing user in check-mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members_must_exist: yes append_members: yes members: - - 'not_existent@localhost' + - 'not_existent@%' + register: result ignore_errors: yes check_mode: yes - - name: assert failure + + - name: Assert nonexistent user in check-mode is failed assert: that: - result is failed - - name: try failing on not-existing user in check-mode - <<: *task_params + - name: Try failing on not-existing user in check-mode mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members_must_exist: no append_members: yes members: - - 'not_existent@localhost' + - 'not_existent@%' + register: result check_mode: yes + - name: Check for lack of change assert: that: - result is not changed - - name: try failing on not-existing user - <<: *task_params + - name: Try failing on not-existing user mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members_must_exist: yes append_members: yes members: - - 'not_existent@localhost' + - 'not_existent@%' + register: result ignore_errors: yes - - name: assert failure + + - name: Assert nonexistent user with members_must_exist is failed assert: that: - result is failed - - name: try failing on not-existing user - <<: *task_params + - name: Try failing on not-existing user mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members_must_exist: no append_members: yes members: - - 'not_existent@localhost' - - name: Check for lack of change + - 'not_existent@%' + register: result + + - name: Assert nonexistent user with members_must_exist=no is not changed assert: that: - result is not changed @@ -1344,131 +1357,131 @@ # ########## - name: Create test DBs - <<: *task_params mysql_query: <<: *mysql_params query: 'CREATE DATABASE {{ item }}' loop: - - '{{ test_db1 }}' - - '{{ test_db2 }}' + - 'test_db1' + - 'test_db2' + register: result - - name: Create table {{ test_table }} - <<: *task_params + - name: Create table test_table mysql_query: <<: *mysql_params login_db: '{{ item }}' - query: 'CREATE TABLE {{ test_table }} (id int)' + query: 'CREATE TABLE test_table (id int)' loop: - - '{{ test_db1 }}' - - '{{ test_db2 }}' + - 'test_db1' + - 'test_db2' + register: result - - name: Check grants - <<: *task_params + - name: Query grants for role0 mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role0 }}" + query: "SHOW GRANTS FOR role0" + register: result - - name: Check + - name: Assert grants for role0 in mysql assert: that: - - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" - - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" - - result.rowcount.0 == 2 - when: install_type == 'mysql' + - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" + - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" + - result.rowcount.0 == 2 + when: db_engine == 'mysql' - - name: Check (mariadb) + - name: Assert grants for role0 in mariadb assert: that: - - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" - - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" - - result.rowcount.0 == 2 - when: install_type == 'mariadb' + - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" + - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" + - result.rowcount.0 == 2 + when: db_engine == 'mariadb' - name: Append privs in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - priv: '{{ test_db1 }}.{{ test_table }}:SELECT,INSERT/{{ test_db2 }}.{{ test_table }}:DELETE' + priv: 'test_db1.test_table:SELECT,INSERT/test_db2.test_table:DELETE' append_privs: yes + register: result check_mode: yes - - name: Check + - name: Assert append privs in check_mode is changed assert: that: - - result is changed + - result is changed - - name: Check grants - <<: *task_params + - name: Query grants for role0 mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role0 }}" + query: "SHOW GRANTS FOR role0" + register: result - - name: Check + - name: Assert grants for role0 in mysql assert: that: - - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" - - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" - - result.rowcount.0 == 2 - when: install_type == 'mysql' + - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" + - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" + - result.rowcount.0 == 2 + when: db_engine == 'mysql' - - name: Check (mariadb) + - name: Assert grants for role0 in mariadb assert: that: - - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" - - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" - - result.rowcount.0 == 2 - when: install_type == 'mariadb' + - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" + - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" + - result.rowcount.0 == 2 + when: db_engine == 'mariadb' - name: Append privs - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - priv: '{{ test_db1 }}.{{ test_table }}:SELECT,INSERT/{{ test_db2 }}.{{ test_table }}:DELETE' + priv: 'test_db1.test_table:SELECT,INSERT/test_db2.test_table:DELETE' append_privs: yes + register: result - - name: Check + - name: Assert that append privs is changed assert: that: - - result is changed + - result is changed - - name: Check grants - <<: *task_params + - name: Query grants for role0 mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role0 }}" + query: "SHOW GRANTS FOR role0" + register: result - - name: Check + - name: Assert grants for role0 in mysql assert: that: - - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" - - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" - - result.query_result.0.2["Grants for role0@%"] == "GRANT SELECT, INSERT ON `test_db1`.`test_table` TO `role0`@`%`" - - result.query_result.0.3["Grants for role0@%"] == "GRANT DELETE ON `test_db2`.`test_table` TO `role0`@`%`" - - result.rowcount.0 == 4 - when: install_type == 'mysql' + - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT, INSERT ON *.* TO `role0`@`%`" + - result.query_result.0.1["Grants for role0@%"] == "GRANT UPDATE ON `mysql`.* TO `role0`@`%`" + - result.query_result.0.2["Grants for role0@%"] == "GRANT SELECT, INSERT ON `test_db1`.`test_table` TO `role0`@`%`" + - result.query_result.0.3["Grants for role0@%"] == "GRANT DELETE ON `test_db2`.`test_table` TO `role0`@`%`" + - result.rowcount.0 == 4 + when: db_engine == 'mysql' - - name: Check (mariadb) + - name: Assert grants for role0 in mariadb assert: that: - - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" - - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" - - result.query_result.0.2["Grants for role0"] == "GRANT SELECT, INSERT ON `test_db1`.`test_table` TO `role0`" - - result.query_result.0.3["Grants for role0"] == "GRANT DELETE ON `test_db2`.`test_table` TO `role0`" - - result.rowcount.0 == 4 - when: install_type == 'mariadb' + - result.query_result.0.0["Grants for role0"] == "GRANT SELECT, INSERT ON *.* TO `role0`" + - result.query_result.0.1["Grants for role0"] == "GRANT UPDATE ON `mysql`.* TO `role0`" + - result.query_result.0.2["Grants for role0"] == "GRANT SELECT, INSERT ON `test_db1`.`test_table` TO `role0`" + - result.query_result.0.3["Grants for role0"] == "GRANT DELETE ON `test_db2`.`test_table` TO `role0`" + - result.rowcount.0 == 4 + when: db_engine == 'mariadb' - name: Append privs again in check_mode - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - priv: '{{ test_db1 }}.{{ test_table }}:SELECT,INSERT/{{ test_db2 }}.{{ test_table }}:DELETE' + priv: 'test_db1.test_table:SELECT,INSERT/test_db2.test_table:DELETE' append_privs: yes + register: result check_mode: yes # TODO it must be changed. The module uses user_mod function @@ -1477,173 +1490,171 @@ # https://github.com/ansible-collections/community.mysql/issues/50#issuecomment-871216825 # and it's also failed. Create an issue after the module is merged to avoid conflicts. # TODO Fix this after user_mod is fixed. - - name: Check + - name: Assert that append privs again in check_mode is changed assert: that: - - result is changed + - result is changed - name: Append privs again - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - priv: '{{ test_db1 }}.{{ test_table }}:SELECT,INSERT/{{ test_db2 }}.{{ test_table }}:DELETE' + priv: 'test_db1.test_table:SELECT,INSERT/test_db2.test_table:DELETE' append_privs: yes + register: result - - name: Check that there's no change + - name: Assert that append privs again is not changed assert: that: - - result is not changed + - result is not changed - name: Rewrite privs - <<: *task_params mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present priv: '*.*': 'SELECT' + register: result - - name: Check + - name: Assert that rewrite privs is changed assert: that: - - result is changed + - result is changed - - name: Check grants - <<: *task_params + - name: Query grants for role0 mysql_query: <<: *mysql_params - query: "SHOW GRANTS FOR {{ role0 }}" + query: "SHOW GRANTS FOR role0" + register: result - - name: Check + - name: Assert grants for role0 in mysql assert: that: - - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT ON *.* TO `role0`@`%`" - - result.rowcount.0 == 1 - when: install_type == 'mysql' + - result.query_result.0.0["Grants for role0@%"] == "GRANT SELECT ON *.* TO `role0`@`%`" + - result.rowcount.0 == 1 + when: db_engine == 'mysql' - - name: Check (mariadb) + - name: Assert grants for role0 in mariadb assert: that: - - result.query_result.0.0["Grants for role0"] == "GRANT SELECT ON *.* TO `role0`" - - result.rowcount.0 == 1 - when: install_type == 'mariadb' + - result.query_result.0.0["Grants for role0"] == "GRANT SELECT ON *.* TO `role0`" + - result.rowcount.0 == 1 + when: db_engine == 'mariadb' # ################# # Test admin option # ################# - - name: Drop role - <<: *task_params + - name: Drop role0 mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: absent + register: result - - name: Create role with admin - <<: *task_params + - name: Create role0 with admin mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - admin: '{{ user0 }}@localhost' + admin: 'user0@%' + register: result ignore_errors: yes - - name: Check with MySQL + - name: Assert expected error message for mysql assert: that: - - result is failed - - result.msg is search('option can be used only with MariaDB') - when: install_type == 'mysql' + - result is failed + - result.msg is search('option can be used only with MariaDB') + when: db_engine == 'mysql' - - name: Check with MariaDB + - name: Assert create role0 in mariadb is changed assert: that: - - result is changed - when: install_type == 'mariadb' + - result is changed + when: db_engine == 'mariadb' - - name: Check in DB - <<: *task_params + - name: Query role0 in mariadb mysql_query: <<: *mysql_params - query: "SELECT 1 FROM mysql.user WHERE User = '{{ role0 }}' AND Host = ''" - when: install_type == 'mariadb' + query: "SELECT 1 FROM mysql.user WHERE User = 'role0' AND Host = ''" + register: result + when: db_engine == 'mariadb' - - name: Check + - name: Assert that query role0 in mariadb returns 1 row assert: that: - - result.rowcount.0 == 1 - when: install_type == 'mariadb' + - result.rowcount.0 == 1 + when: db_engine == 'mariadb' - - name: Create role with admin again - <<: *task_params + - name: Create role0 with admin again mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present - admin: '{{ user0 }}@localhost' + admin: 'user0@%' + register: result ignore_errors: yes - - name: Check with MySQL + - name: Assert expected error message in mysql again assert: that: - - result is failed - - result.msg is search('option can be used only with MariaDB') - when: install_type == 'mysql' + - result is failed + - result.msg is search('option can be used only with MariaDB') + when: db_engine == 'mysql' - - name: Check with MariaDB + - name: Assert create role0 in mariadb is not changed assert: that: - - result is not changed - when: install_type == 'mariadb' + - result is not changed + when: db_engine == 'mariadb' # Try to grant a role to a user who does not exist - - name: Create role with admin again - <<: *task_params + - name: Create role0 with admin again mysql_role: <<: *mysql_params - name: '{{ role0 }}' + name: 'role0' state: present members: - - '{{ nonexistent }}@localhost' + - 'nonexistent@%' + register: result ignore_errors: yes - - name: Check + - name: Assert that create role0 with admin again is failed assert: that: - - result is failed - - result.msg is search('does not exist') + - result is failed + - result.msg is search('does not exist') always: - # Clean up - - name: Drop DBs - mysql_query: - <<: *mysql_params - query: 'DROP DATABASE {{ item }}' - loop: - - '{{ test_db }}' - - '{{ test_db1 }}' - - '{{ test_db2 }}' - - name: Drop users - <<: *task_params - mysql_user: - <<: *mysql_params - name: '{{ item }}' - state: absent - loop: - - '{{ user0 }}' - - '{{ user1 }}' - - '{{ user2 }}' - - - name: Drop roles - <<: *task_params - mysql_role: - <<: *mysql_params - name: '{{ item }}' - state: absent - loop: - - '{{ role0 }}' - - test - - '{{ role3 }}' + - name: Clean up DBs + mysql_query: + <<: *mysql_params + query: 'DROP DATABASE IF EXISTS {{ item }}' + loop: + - 'test_db' + - 'test_db1' + - 'test_db2' + + - name: Clean up users + mysql_user: + <<: *mysql_params + name: '{{ item }}' + state: absent + loop: + - 'user0' + - 'user1' + - 'user2' + + - name: Clean up roles + mysql_role: + <<: *mysql_params + name: '{{ item }}' + state: absent + loop: + - 'role0' + - 'test' + - 'role3' diff --git a/tests/integration/targets/test_mysql_role/tasks/test_priv_subtract.yml b/tests/integration/targets/test_mysql_role/tasks/test_priv_subtract.yml index 95d2f1d1..b79a1cb7 100644 --- a/tests/integration/targets/test_mysql_role/tasks/test_priv_subtract.yml +++ b/tests/integration/targets/test_mysql_role/tasks/test_priv_subtract.yml @@ -3,7 +3,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: @@ -11,20 +11,18 @@ - name: Create test databases mysql_db: <<: *mysql_params - name: '{{ item }}' + name: data1 state: present - loop: - - data1 - name: Create a role with an initial set of privileges mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' priv: 'data1.*:SELECT,INSERT' state: present - name: Run command to show privileges for role (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ role2 }}'\"" + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR 'role2'\"" register: result - name: Assert that the initial set of privileges matches what is expected @@ -35,7 +33,7 @@ - name: Subtract privileges that are not in the current privileges, which should be a no-op mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' priv: 'data1.*:DELETE' subtract_privs: yes state: present @@ -48,7 +46,7 @@ - result is not changed - name: Run command to show privileges for role (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ role2 }}'\"" + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR 'role2'\"" register: result - name: Assert that the permissions still match what was originally granted @@ -59,7 +57,7 @@ - name: Subtract existing and not-existing privileges, but not all mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' priv: 'data1.*:INSERT,DELETE' subtract_privs: yes state: present @@ -72,7 +70,7 @@ - result is changed - name: Run command to show privileges for role (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ role2 }}'\"" + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR 'role2'\"" register: result - name: Assert that the permissions were not changed if check_mode is set to 'yes' @@ -90,7 +88,7 @@ - name: Try to subtract invalid privileges mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' priv: 'data1.*:INVALID' subtract_privs: yes state: present @@ -103,7 +101,7 @@ - result is not changed - name: Run command to show privileges for role (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ role2 }}'\"" + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR 'role2'\"" register: result - name: Assert that the permissions were not changed with check_mode=='yes' @@ -121,7 +119,7 @@ - name: trigger failure by trying to subtract and append privileges at the same time mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' priv: 'data1.*:SELECT' subtract_privs: yes append_privs: yes @@ -136,7 +134,7 @@ - result is failed - name: Run command to show privileges for role (expect privileges in stdout) - command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ role2 }}'\"" + command: "{{ mysql_command }} -e \"SHOW GRANTS FOR 'role2'\"" register: result - name: Assert that the permissions stayed the same, with check_mode=='yes' @@ -156,13 +154,11 @@ - name: Drop test databases mysql_db: <<: *mysql_params - name: '{{ item }}' + name: 'data1' state: present - loop: - - data1 - name: Drop test role mysql_role: <<: *mysql_params - name: '{{ role2 }}' + name: 'role2' state: absent diff --git a/tests/integration/targets/test_mysql_user/defaults/main.yml b/tests/integration/targets/test_mysql_user/defaults/main.yml index 5cf9074b..a87914cb 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 a7ace5d1..4be5f587 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 98610842..00000000 --- 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 d95d9d21..00000000 --- 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 deleted file mode 100644 index 9984ea99..00000000 --- a/tests/integration/targets/test_mysql_user/tasks/create_user.yml +++ /dev/null @@ -1,46 +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: Drop mysql user if exists - mysql_user: - <<: *mysql_params - name: '{{ user_name_1 }}' - state: absent - ignore_errors: yes - - # ============================================================ - - 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 7d789ef8..7f5934fc 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-121.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-121.yml @@ -1,75 +1,73 @@ --- + - 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: register: result - ignore_errors: yes + ignore_errors: true - - assert: + - name: >- + Issue-121 | Assert error granting privileges with incompatible tls_requires + option + assert: that: - result is failed - result.msg is search('Error granting privileges') - - 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 index 167b69b7..bea41a84 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-265.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-265.yml @@ -3,52 +3,54 @@ 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 if exists + - name: Issue-265 | Drop mysql user if exists mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes # Tests with force_context: yes # Test user creation - - name: create mysql user {{user_name_1}} + - name: Issue-265 | Create mysql user {{ user_name_1 }} mysql_user: <<: *mysql_params - name: '{{ user_name_1 }}' - password: '{{ user_password_1 }}' + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" state: present force_context: yes register: result - - name: assert output message mysql user was created + - name: Issue-265 | Assert user was created assert: that: - result is changed - - include: assert_user.yml user_name={{user_name_1}} + - include: utils/assert_user.yml user_name={{ user_name_1 }} user_host=localhost # Test user removal - - name: remove mysql user {{user_name_1}} + - name: Issue-265 | remove mysql user {{ user_name_1 }} mysql_user: <<: *mysql_params - name: '{{user_name_1}}' - password: '{{user_password_1}}' + name: "{{ user_name_1 }}" + host_all: true + password: "{{ user_password_1 }}" state: absent force_context: yes register: result - - name: assert output message mysql user was removed + - name: Issue-265 | Assert user was removed assert: that: - result is changed # Test blank user removal - - name: create blank mysql user to be removed later + - name: Issue-265 | Create blank mysql user to be removed later mysql_user: <<: *mysql_params name: "" @@ -56,7 +58,7 @@ force_context: yes password: 'KJFDY&D*Sfuydsgf' - - name: remove blank mysql user with hosts=all (expect changed) + - name: Issue-265 | Remove blank mysql user with hosts=all (expect changed) mysql_user: <<: *mysql_params user: "" @@ -65,12 +67,12 @@ force_context: yes register: result - - name: assert changed is true for removing all blank users + - name: Issue-265 | Assert changed is true for removing all blank users assert: that: - result is changed - - name: remove blank mysql user with hosts=all (expect ok) + - name: Issue-265 | Remove blank mysql user with hosts=all (expect ok) mysql_user: <<: *mysql_params user: "" @@ -79,57 +81,58 @@ state: absent register: result - - name: assert changed is true for removing all blank users + - name: Issue-265 | Assert changed is true for removing all blank users assert: that: - result is not changed - - include: assert_no_user.yml user_name={{user_name_1}} + - include: utils/assert_no_user.yml user_name={{user_name_1}} # Tests with force_context: no # Test user creation - - name: Drop mysql user if exists + - name: Issue-265 | Drop mysql user if exists mysql_user: <<: *mysql_params - name: '{{ user_name_1 }}' + name: "{{ user_name_1 }}" + host_all: true state: absent ignore_errors: yes # Tests with force_context: yes # Test user creation - - name: create mysql user {{user_name_1}} + - name: Issue-265 | Create mysql user {{user_name_1}} mysql_user: <<: *mysql_params - name: '{{ user_name_1 }}' - password: '{{ user_password_1 }}' + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" state: present force_context: yes register: result - - name: assert output message mysql user was created + - name: Issue-265 | Assert output message mysql user was created assert: that: - result is changed - - include: assert_user.yml user_name={{user_name_1}} + - include: utils/assert_user.yml user_name={{ user_name_1 }} user_host=localhost # Test user removal - - name: remove mysql user {{user_name_1}} + - name: Issue-265 | Remove mysql user {{ user_name_1 }} mysql_user: <<: *mysql_params - name: '{{user_name_1}}' - password: '{{user_password_1}}' + name: "{{ user_name_1 }}" + password: "{{ user_password_1 }}" state: absent force_context: no register: result - - name: assert output message mysql user was removed + - name: Issue-265 | Assert output message mysql user was removed assert: that: - result is changed # Test blank user removal - - name: create blank mysql user to be removed later + - name: Issue-265 | Create blank mysql user to be removed later mysql_user: <<: *mysql_params name: "" @@ -137,7 +140,7 @@ force_context: no password: 'KJFDY&D*Sfuydsgf' - - name: remove blank mysql user with hosts=all (expect changed) + - name: Issue-265 | Remove blank mysql user with hosts=all (expect changed) mysql_user: <<: *mysql_params user: "" @@ -146,12 +149,12 @@ force_context: no register: result - - name: assert changed is true for removing all blank users + - name: Issue-265 | Assert changed is true for removing all blank users assert: that: - result is changed - - name: remove blank mysql user with hosts=all (expect ok) + - name: Issue-265 | Remove blank mysql user with hosts=all (expect ok) mysql_user: <<: *mysql_params user: "" @@ -160,9 +163,9 @@ state: absent register: result - - name: assert changed is true for removing all blank users + - name: Issue-265 | Assert changed is true for removing all blank users assert: that: - result is not changed - - include: assert_no_user.yml user_name={{user_name_1}} + - include: utils/assert_no_user.yml user_name={{ user_name_1 }} 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 d56965a6..51a20918 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml @@ -9,80 +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 31e6edfe..17eb2000 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 1c0af682..a7657f8a 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 5a029b8b..188628fe 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,129 +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 - session_vars: - sort_buffer_size: 1024 - register: result - - - name: assert output message mysql user was not created - assert: - that: - - result is not changed - - # Try to set wrong session variable, must fail - - name: create mysql user trying to set global variable which is forbidden - mysql_user: - <<: *mysql_params - name: '{{user_name_1}}' - password: '{{user_password_1}}' - state: present - session_vars: - max_connections: 1000 - register: result - ignore_errors: true - - - name: we cannot set a global variable - assert: - that: - - result is failed - - result.msg is search('is a GLOBAL variable') - - # ============================================================ - # 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] }}' @@ -171,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 }}' @@ -206,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 @@ -221,8 +139,8 @@ <<: *mysql_params name: '{{ user_name_1 }}' priv: - - unsuitable - - type + - unsuitable + - type append_privs: yes host_all: yes password: '{{ user_password_1 }}' @@ -235,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 }}' @@ -244,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 @@ -254,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. @@ -266,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 @@ -306,7 +224,7 @@ - issue_465 # Tests for the TLS requires dictionary - - include: tls_requirements.yml + - include: test_tls_requirements.yml - import_tasks: issue-29511.yaml tags: @@ -323,4 +241,4 @@ # https://github.com/ansible-collections/community.mysql/issues/231 - include: test_user_grants_with_roles_applied.yml - - include: revoke_only_grant.yml \ No newline at end of file + - 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 7a2c9e96..00000000 --- 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 00000000..cc6850cc --- /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 583f7c06..51d4a29f 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,33 +77,34 @@ 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: Try to append invalid privileges + - 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 @@ -108,7 +113,7 @@ register: result ignore_errors: true - - name: Assert that there wasn't a change in privileges if check_mode is set to 'no' + - name: Priv append | Assert that there wasn't a change in privileges if check_mode is set to 'no' assert: that: - result is failed @@ -123,11 +128,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 d54c9467..82385e19 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 index 75952432..b63f6649 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_priv_subtract.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_priv_subtract.yml @@ -1,42 +1,45 @@ +--- # Test code to ensure that subtracting privileges will not result in unnecessary changes. - 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 substract | Create test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 + - data1 - - name: Create a user with an initial set of privileges + - name: Priv substract | 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' 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 substract | 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 substract | Assert that the initial set of privileges matches what is expected assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" - - name: Subtract privileges that are not in the current privileges, which should be a no-op + - name: Priv substract | Subtract privileges that are not in the current privileges, which should be a no-op mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:DELETE' subtract_privs: yes @@ -44,24 +47,25 @@ check_mode: '{{ enable_check_mode }}' register: result - - name: Assert that there wasn't a change in permissions + - name: Priv substract | 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 substract | 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 substract | Assert that the permissions still match what was originally granted assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" - - name: Subtract existing and not-existing privileges, but not all + - name: Priv substract | Subtract existing and not-existing privileges, but not all mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:INSERT,DELETE' subtract_privs: yes @@ -69,31 +73,32 @@ check_mode: '{{ enable_check_mode }}' register: result - - name: Assert that there was a change because permissions were/would be revoked on data1.* + - name: Priv substract | Assert that there was a change because permissions were/would be revoked on 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 substract | 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 not changed if check_mode is set to 'yes' + - name: Priv substract | Assert that the permissions were not changed if check_mode is set to 'yes' assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" when: enable_check_mode == 'yes' - - name: Assert that only DELETE was revoked if check_mode is set to 'no' + - name: Priv substract | Assert that only DELETE was revoked if check_mode is set to 'no' assert: that: - "'GRANT SELECT ON `data1`.*' in result.stdout" when: enable_check_mode == 'no' - - name: Try to subtract invalid privileges + - name: Priv substract | Try to subtract invalid privileges mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:INVALID' subtract_privs: yes @@ -101,31 +106,32 @@ check_mode: '{{ enable_check_mode }}' register: result - - name: Assert that there was no change because invalid permissions are ignored + - name: Priv substract | Assert that there was no change because invalid permissions are ignored 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 substract | 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 not changed with check_mode=='yes' + - name: Priv substract | Assert that the permissions were not changed with check_mode=='yes' assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" when: enable_check_mode == 'yes' - - name: Assert that the permissions were not changed with check_mode=='no' + - name: Priv substract | Assert that the permissions were not changed with check_mode=='no' assert: that: - "'GRANT SELECT ON `data1`.*' in result.stdout" when: enable_check_mode == 'no' - - name: trigger failure by trying to subtract and append privileges at the same time + - name: Priv substract | Trigger failure by trying to subtract and append privileges at the same time mysql_user: <<: *mysql_params name: '{{ user_name_4 }}' + host: '%' password: '{{ user_password_4 }}' priv: 'data1.*:SELECT' subtract_privs: yes @@ -135,22 +141,22 @@ register: result ignore_errors: true - - name: Assert the previous execution failed + - name: Priv substract | Assert the previous execution failed assert: that: - result is failed - - 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 substract | 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 stayed the same, with check_mode=='yes' + - name: Priv substract | Assert that the permissions stayed the same, with check_mode=='yes' assert: that: - "'GRANT SELECT, INSERT ON `data1`.*' in result.stdout" when: enable_check_mode == 'yes' - - name: Assert that the permissions stayed the same, with check_mode=='no' + - name: Priv substract | Assert that the permissions stayed the same, with check_mode=='no' assert: that: - "'GRANT SELECT ON `data1`.*' in result.stdout" @@ -158,16 +164,12 @@ ########## # Clean up - - name: Drop test databases + - name: Priv substract | Drop test databases mysql_db: <<: *mysql_params name: '{{ item }}' state: present loop: - - data1 + - data1 - - 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_privs.yml b/tests/integration/targets/test_mysql_user/tasks/test_privs.yml index b9581f73..9801e195 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,24 +156,26 @@ 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 with a long privileges list (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 @@ -175,20 +183,15 @@ # 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: Assert that priv did not change + - name: Privs | Assert that priv did not change assert: that: - result is not changed - - 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 }}" # ============================================================ - - name: grant all privileges with grant option + - name: Privs | Grant all privileges with grant option mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -197,23 +200,23 @@ state: present register: result - - name: Assert that priv changed + - name: Privs | Assert that priv changed assert: that: - result is changed - - name: Collect user info by host + - name: Privs | Collect user info by host community.mysql.mysql_info: <<: *mysql_params filter: "users" register: mysql_info_about_users - - name: Assert that 'GRANT' permission is present + - name: Privs | Assert that 'GRANT' permission is present assert: that: - mysql_info_about_users.users.localhost.{{ user_name_2 }}.Grant_priv == 'Y' - - name: Test idempotency (expect ok) + - name: Privs | Test idempotency (expect ok) mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -223,24 +226,24 @@ register: result # FIXME: on mysql >=8 there's always a change (ALL PRIVILEGES -> specific privileges) - - name: Assert that priv did not change + - name: Privs | Assert that priv did not change assert: that: - result is not changed - - name: Collect user info by host + - name: Privs | Collect user info by host community.mysql.mysql_info: <<: *mysql_params filter: "users" register: mysql_info_about_users - - name: Assert that 'GRANT' permission is present + - 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: update user with invalid privileges + - name: Privs | Update user with invalid privileges mysql_user: <<: *mysql_params name: '{{ user_name_2 }}' @@ -250,15 +253,10 @@ 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 - "'Error granting privileges' in result.msg" - - 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 index edf4a0f3..2e6a41e8 100644 --- 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 @@ -5,13 +5,13 @@ 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 a user with parameters that will always cause an exception + - name: Privs issue 465 | Create a user with parameters that will always cause an exception mysql_user: <<: *mysql_params name: user_issue_465 @@ -21,7 +21,7 @@ ignore_errors: true register: result - - name: assert output message for current privileges + - name: Privs issue 465 | Assert output message for current privileges assert: that: - result is failed 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 736adb33..7c2b97b0 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/revoke_only_grant.yml b/tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml similarity index 61% rename from tests/integration/targets/test_mysql_user/tasks/revoke_only_grant.yml rename to tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml index 19b9b6a9..de0fc629 100644 --- a/tests/integration/targets/test_mysql_user/tasks/revoke_only_grant.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_revoke_only_grant.yml @@ -3,17 +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: Drop mysql user if exists - mysql_user: - <<: *mysql_params - name: '{{ user_name_1 }}' - state: absent - ignore_errors: true + - include: utils/remove_user.yml user_name={{ user_name_1 }} - - name: create user with two grants + - name: Revoke only grants | Create user with two grants mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" @@ -21,7 +16,7 @@ update_password: on_create priv: '*.*:SELECT,GRANT' - - name: user must have only on priv, grant priv must be dropped + - name: Revoke only grants | Revoke grant priv from db_user1 register: result mysql_user: <<: *mysql_params @@ -30,12 +25,13 @@ update_password: on_create priv: '*.*:SELECT' - - assert: + - name: Revoke only grants | Assert that db_user1 only have one priv left + assert: that: - result is not failed - result is changed - - name: immutable - user must have only on priv, grant priv must be dropped + - name: Revoke only grants | Update db_user1 again to test idempotence register: result mysql_user: <<: *mysql_params @@ -44,15 +40,11 @@ update_password: on_create priv: '*.*:SELECT' - - assert: + - name: Revoke only grants | Assert that task is idempotent + assert: that: - - result is not failed + - result is succeeded - result is not changed always: - - name: drop user - mysql_user: - <<: *mysql_params - name: '{{ user_name_1 }}' - state: absent - ignore_errors: true + - 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 7bf142ec..f85ae3b9 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 index c9b74bbc..428c1ef7 100644 --- a/tests/integration/targets/test_mysql_user/tasks/test_update_password.yml +++ b/tests/integration/targets/test_mysql_user/tasks/test_update_password.yml @@ -1,10 +1,11 @@ +--- # Tests scenarios for both plaintext and encrypted user passwords. - vars: mysql_parameters: login_user: '{{ mysql_user }}' login_password: '{{ mysql_password }}' - login_host: 127.0.0.1 + login_host: '{{ mysql_host }}' login_port: '{{ mysql_primary_port }}' test_password1: kbB9tcx5WOGVGfzV test_password1_hash: '*AF6A7F9D038475C17EE46564F154104877EE5037' @@ -15,10 +16,10 @@ block: - - include_tasks: assert_user_password.yml + - include_tasks: utils/assert_user_password.yml vars: username: "{{ item.username }}" - host: '127.0.0.1' + host: "%" update_password: "{{ item.update_password }}" password: "{{ test_password1 }}" expect_change: "{{ item.expect_change }}" @@ -48,10 +49,10 @@ expect_change: false # same user, new password - - include_tasks: assert_user_password.yml + - include_tasks: utils/assert_user_password.yml vars: username: "{{ item.username }}" - host: '127.0.0.1' + host: "%" update_password: "{{ item.update_password }}" password: "{{ test_password2 }}" expect_change: "{{ item.expect_change }}" @@ -72,7 +73,7 @@ expect_password_hash: "{{ test_password1_hash }}" # new user, new password - - include_tasks: assert_user_password.yml + - include_tasks: utils/assert_user_password.yml vars: username: "{{ item.username }}" host: '::1' @@ -110,7 +111,7 @@ expect_password_hash: "{{ test_password2_hash }}" # another new user, another new password and multiple existing users with varying passwords - - include_tasks: assert_user_password.yml + - include_tasks: utils/assert_user_password.yml vars: username: "{{ item.username }}" host: '2001:db8::1' 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 8ee738ec..c6a1327d 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 @@ -45,14 +44,14 @@ - "'GRANT SELECT ON `data1`.*' in result.stdout" - "'GRANT SELECT ON `data2`.*' in result.stdout" - - name: Create role + - name: User grants with roles applied | Create role mysql_role: <<: *mysql_params name: test231 members: - - '{{ user_name_3 }}@localhost' + - '{{ 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 }}' @@ -61,11 +60,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" @@ -73,22 +72,18 @@ ########## # Clean up - - name: Drop test databases + - name: User grants with roles applied | Drop test databases mysql_db: <<: *mysql_params name: '{{ item }}' - state: present + state: absent loop: - - data1 - - data2 + - data1 + - data2 - - name: Drop test user - mysql_user: - <<: *mysql_params - name: '{{ user_name_3 }}' - state: absent + - include: utils/remove_user.yml user_name={{ user_name_3 }} - - name: Drop test role + - name: User grants with roles applied | Drop test role mysql_role: <<: *mysql_params name: test231 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 57d8d295..d98c92c9 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 264d8bd3..8d7740b0 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: Get user information - 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: 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', '>=')) - - - include: assert_user.yml user_name={{ test_user_name }} 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: Get user information - 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: Check that the expected plugin type is set - assert: - that: + - 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: Plugin auth | Get user information (empty auth string) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + register: show_create_user + + - name: Plugin auth | Check that the module made a change (empty auth string) + assert: + that: + - result is changed + + - 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: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }} + + - 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: Plugin auth | Get user information (sha256_password) + command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\"" + register: show_create_user + + - name: Plugin auth | Check that the module made a change (sha256_password) + assert: + that: + - result is changed + + - 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 00000000..6fc4fbca --- /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 00000000..e6bd23fb --- /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 ba045eb2..d95e53b8 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 00000000..b255ec45 --- /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 00000000..473cecee --- /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 6d0e2ec8..779eeade 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 f1174ff2..01ee3db7 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 96d196dd..e64c5a7a 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 aa01ddbf..10a91541 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: @@ -25,6 +25,7 @@ mysql_user: <<: *mysql_params name: '{{ user_name_1 }}' + host_all: true state: absent ignore_errors: yes @@ -32,6 +33,7 @@ mysql_user: <<: *mysql_params name: "{{ user_name_1 }}" + host: '%' password: "{{ user_password_1 }}" priv: '*.*:ALL,GRANT' tls_requires: @@ -42,7 +44,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 @@ -51,19 +53,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 @@ -78,5 +82,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 ed34966c..c8ae3e8f 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 00000000..160cfba8 --- /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 != {}