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@<gateway ip addr> 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) <jorge.rodriguez@futurice.com>

* Reformat file path

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* Fix link URI

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* Fix link URI

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* Lint

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* Lint

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* Add better task name

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>

* 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) <jorge.rodriguez@futurice.com>
This commit is contained in:
Laurent Indermühle 2023-03-21 08:16:09 +01:00 committed by GitHub
parent 9b8455c2e6
commit 6970aef8f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
126 changed files with 3942 additions and 2822 deletions

View file

@ -1,3 +1,5 @@
---
mysql_host: "{{ gateway_addr }}"
master_port: 3306
standby_port: 3307
test_db: test_db

View file

@ -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

View file

@ -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 }}"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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') }}"

View file

@ -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

View file

@ -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 -%}

View file

@ -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

View file

@ -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('.','_') }}"

View file

@ -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 }}"

View file

@ -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

View file

@ -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

View file

@ -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') }}"

View file

@ -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

View file

@ -1 +0,0 @@
{{ dbdeployer_version }}

View file

@ -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 }}"

View file

@ -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

View file

@ -1,2 +1,2 @@
dependencies:
- setup_mysql
- setup_controller

View file

@ -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

View file

@ -1,45 +1,46 @@
---
- set_fact:
latin1_file1: "{{tmp_dir}}/{{file}}"
- name: Encoding | Set fact
set_fact:
latin1_file1: "{{ tmp_dir }}/{{ file }}"
- name: Deleting Latin1 encoded Database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
name: '{{ db_latin1_name }}'
state: absent
- name: create Latin1 encoded database
- name: Encoding | Create Latin1 encoded database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
name: '{{ db_latin1_name }}'
state: present
encoding: latin1
- name: create a table in Latin1 database
- name: Encoding | Create a table in Latin1 database
command: "{{ mysql_command }} {{ db_latin1_name }} -e \"create table testlatin1(id int, name varchar(100))\""
# Inserting a string in latin1 into table, , this string be tested later,
# so report any change of content in the test too
- name: inserting data into Latin1 database
- name: Encoding | Inserting data into Latin1 database
command: "{{ mysql_command }} {{ db_latin1_name }} -e \"insert into testlatin1 value(47,'Amédée Bôlüt')\""
- name: selecting table
- name: Encoding | Selecting table
command: "{{ mysql_command }} {{ db_latin1_name }} -e \"select * from testlatin1\""
register: output
- name: Dumping a table in Latin1 database
- name: Encoding | Dumping a table in Latin1 database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
name: "{{ db_latin1_name }}"
encoding: latin1
@ -49,30 +50,30 @@
- assert:
that:
- result is changed
- result is changed
- name: state dump - file name should exist
- name: Encoding | State dump - file name should exist (latin1_file1)
file:
name: '{{ latin1_file1 }}'
state: file
- name: od the file and check of latin1 encoded string is present
- name: od the file and check of latin1 encoded string is present
shell: grep -a 47 {{ latin1_file1 }} | od -c |grep "A m 351 d 351 e B 364\|A m 303 251 d 303 251 e B 303"
- name: Dropping {{ db_latin1_name }} database
- name: Encoding | Dropping {{ db_latin1_name }} database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
name: '{{ db_latin1_name }}'
state: absent
- name: Importing the latin1 mysql script
- name: Encoding | Importing the latin1 mysql script
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
state: import
encoding: latin1
@ -80,20 +81,25 @@
target: "{{ latin1_file1 }}"
register: result
- assert:
- name: Encoding | Assert that importing latin1 is changed
assert:
that:
- result is changed
- result is changed
- name: check encoding of table
shell: "{{ mysql_command }} {{ db_latin1_name }} -e \"SHOW FULL COLUMNS FROM testlatin1\""
- name: Encoding | Check encoding of table
ansible.builtin.command:
cmd: >
{{ mysql_command }}
{{ db_latin1_name }}
-e "SHOW FULL COLUMNS FROM {{ db_latin1_name }}.testlatin1"
register: output
failed_when: '"latin1_swedish_ci" not in output.stdout'
- name: remove database
- name: Encoding | Clean up database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
name: '{{ db_latin1_name }}'
state: absent

View file

@ -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

View file

@ -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

View file

@ -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 <http://www.gnu.org/licenses/>.
- 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:

View file

@ -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 }}'

View file

@ -17,113 +17,116 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# ============================================================
- 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 }}'

View file

@ -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 <http://www.gnu.org/licenses/>.
# ============================================================
- 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"

View file

@ -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

View file

@ -1,3 +1,4 @@
---
dependencies:
- setup_mysql
- setup_controller
- setup_remote_tmp_dir

View file

@ -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 }}

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,6 @@
mysql_user: root
mysql_password: msandbox
mysql_host: '{{ gateway_addr }}'
mysql_primary_port: 3307
db_name: data

View file

@ -1,2 +1,3 @@
---
dependencies:
- setup_mysql
- setup_controller

View file

@ -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

View file

@ -1,3 +1,4 @@
---
# Test code for mysql_query module
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
# 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 }}'

View file

@ -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

View file

@ -1,3 +1,3 @@
---
dependencies:
- setup_mysql
- setup_controller

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -1,3 +1,4 @@
---
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
# 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:

View file

@ -1,3 +1,4 @@
---
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@ -5,16 +6,9 @@
mysql_params: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
block:
- name: find out the database version
mysql_info:
<<: *mysql_params
login_port: '{{ mysql_primary_port }}'
filter: version
register: db
- name: Set mysql8022_and_higher
set_fact:
mysql8022_and_higher: false
@ -23,21 +17,31 @@
set_fact:
mysql8022_and_higher: true
when:
- db.version.major > 8 or (db.version.major == 8 and db.version.minor > 0) or (db.version.major == 8 and db.version.minor == 0 and db.version.release >= 22)
- install_type == 'mysql'
- db_engine == 'mysql'
- db_version is version('8.0.22', '>=')
- name: alias mysql command to include default options
set_fact:
mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --protocol=tcp"
# Preparation:
# We use iF NOT EXISTS because the GITHUB Action:
# "ansible-community/ansible-test-gh-action" uses "--retry-on-error".
# If test_mysql_replication fails, test will run again an without the IF
# NOT EXISTS, we see "Error 1396 (HY000): Operation CREATE USER failed..."
# which is misleading.
- name: Create user for mysql replication
shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}"
when: install_type == 'mysql'
shell:
"echo \"CREATE USER IF NOT EXISTS \
'{{ replication_user }}'@'{{ mysql_host }}' \
IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; \
GRANT REPLICATION SLAVE ON *.* TO \
'{{ replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}"
when: db_engine == 'mysql'
- name: Create user for mariadb replication
shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}"
when: install_type == 'mariadb'
shell:
"echo \"CREATE USER IF NOT EXISTS \
'{{ replication_user }}'@'{{ mysql_host }}' \
IDENTIFIED BY '{{ replication_pass }}'; \
GRANT REPLICATION SLAVE ON *.* TO \
'{{ replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}"
when: db_engine == 'mariadb'
- name: Create test database
mysql_db:
@ -47,13 +51,31 @@
name: '{{ test_db }}'
- name: Dump all databases from the primary
shell: 'mysqldump -u{{ mysql_user }} -p{{ mysql_password }} -h{{ mysql_host }} --protocol=tcp -P{{ mysql_primary_port }} --all-databases --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats --master-data=2 > {{ dump_path }}'
shell:
cmd: >-
mysqldump
-u{{ mysql_user }}
-p{{ mysql_password }}
-h{{ mysql_host }}
-P{{ mysql_primary_port }}
--protocol=tcp
--all-databases
--ignore-table=mysql.innodb_index_stats
--ignore-table=mysql.innodb_table_stats
--master-data=2
> {{ dump_path }}
- name: Restore the dump to replica1
shell: '{{ mysql_command }} -P{{ mysql_replica1_port }} < {{ dump_path }}'
shell:
cmd: >-
{{ mysql_command_wo_port }}
-P{{ mysql_replica1_port }} < {{ dump_path }}
- name: Restore the dump to replica2
shell: '{{ mysql_command }} -P{{ mysql_replica2_port }} < {{ dump_path }}'
shell:
cmd: >-
{{ mysql_command_wo_port }}
-P{{ mysql_replica2_port }} < {{ dump_path }}
# Test 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

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -1,2 +1,3 @@
---
dependencies:
- setup_mysql
- setup_controller

View file

@ -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)

View file

@ -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

View file

@ -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'

View file

@ -1,3 +1,4 @@
---
dependencies:
- setup_mysql
- setup_controller
- setup_remote_tmp_dir

View file

@ -1,25 +0,0 @@
# test code to assert no mysql user
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# ============================================================
- 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" }

View file

@ -1,38 +0,0 @@
# test code to assert mysql user
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# ============================================================
- 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

View file

@ -1,46 +0,0 @@
# test code to create mysql user
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
- 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

View file

@ -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 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'\") }}"
content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect {{ mysql_host }}:3307 -showcerts 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'\") }}"
dest: /tmp/cert.pem
delegate_to: localhost
- name: get server version
mysql_info:
<<: *mysql_params
filter: version
register: db_version
- set_fact:
old_user_mgmt: "{{ db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2 | bool }}"
- name: Drop mysql user if exists
- name: Issue-121 | Drop mysql user if exists
mysql_user:
<<: *mysql_params
name: '{{ item }}'
host_all: true
state: absent
ignore_errors: yes
with_items:
ignore_errors: true
loop:
- "{{ user_name_1 }}"
- "{{ user_name_2 }}"
- name: create user with REQUIRESSL privilege (expect failure)
- name: Issue-121 | Create user with REQUIRESSL privilege (expect failure)
mysql_user:
<<: *mysql_params
name: "{{ user_name_1 }}"
password: "{{ user_password_1 }}"
priv: '*.*:SELECT,CREATE USER,REQUIRESSL,GRANT'
register: result
ignore_errors: yes
ignore_errors: true
- assert:
- name: Issue-121 | Assert error granting privileges
assert:
that:
- result is failed
- result.msg is search('Error granting privileges')
- name: create user with both REQUIRESSL privilege and an incompatible tls_requires option
- name: >-
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 }}"

View file

@ -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 }}

View file

@ -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 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'\") }}"
content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect {{ mysql_host }}:3307 -showcerts 2>/dev/null </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'\") }}"
dest: /tmp/cert.pem
delegate_to: localhost
- name: Drop mysql user if exists
- name: Issue-28 | Setup | Drop mysql user if exists
mysql_user:
<<: *mysql_params
name: '{{ user_name_1 }}'
host_all: true
state: absent
ignore_errors: yes
ignore_errors: true
- name: create user with ssl requirement
- name: Issue-28 | Create user with ssl requirement
mysql_user:
<<: *mysql_params
name: "{{ user_name_1 }}"
host: '{{ gateway_addr }}'
password: "{{ user_password_1 }}"
priv: '*.*:ALL,GRANT'
tls_requires:
SSL:
- name: attempt connection with newly created user (expect failure)
- name: Issue-28 | Attempt connection with newly created user (expect failure)
mysql_user:
name: "{{ user_name_2 }}"
password: "{{ user_password_2 }}"
host: 127.0.0.1
host: '{{ gateway_addr }}'
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
ignore_errors: yes
ignore_errors: true
- assert:
- name: Issue-28 | Assert connection failed
assert:
that:
- result is failed
when: connector_name is search('pymysql')
when:
- connector_name == 'pymysql'
- assert:
- name: Issue-28 | Assert connection succeeded
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
- name: Issue-28 | Attempt connection with newly created user ignoring hostname
mysql_user:
name: "{{ user_name_2 }}"
password: "{{ user_password_2 }}"
host: 127.0.0.1
host: '{{ gateway_addr }}'
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
check_hostname: false
register: result
ignore_errors: yes
ignore_errors: true
- assert:
- name: Issue-28 | Assert connection succeeded
assert:
that:
- result is succeeded or 'pymysql >= 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 }}"

View file

@ -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 }}"

View file

@ -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

View file

@ -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
- include: test_revoke_only_grant.yml

View file

@ -1,74 +0,0 @@
# test code to remove mysql user
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
- 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

View file

@ -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

View file

@ -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 }}

View file

@ -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 }}"

View file

@ -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 }}"

View file

@ -1,3 +1,4 @@
---
# test code for privileges for mysql_user module
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
@ -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 }}"

View file

@ -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

View file

@ -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

View file

@ -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 }}

View file

@ -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}}

View file

@ -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'

View file

@ -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
loop:
- data1
- data2
- name: Drop test user
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
state: absent
loop:
- data1
- data2
- name: Drop test role
- include: utils/remove_user.yml user_name={{ user_name_3 }}
- name: User grants with roles applied | Drop test role
mysql_role:
<<: *mysql_params
name: test231

View file

@ -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 }}

View file

@ -1,10 +1,11 @@
---
# Test user plugin auth scenarios.
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_host: '{{ mysql_host }}'
login_port: '{{ mysql_primary_port }}'
test_user_name: 'test_user_plugin_auth'
test_plugin_type: 'mysql_native_password'
@ -21,33 +22,34 @@
# Test plugin auth initially setting a hash and then changing to a different hash.
#
- name: Create user with plugin auth (with hash string)
- name: Plugin auth | Create user with plugin auth (with hash string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_hash_string: '{{ test_plugin_hash }}'
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\""
- name: Plugin auth | Get user information (with hash string)
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = '%'\""
register: show_create_user
- name: Check that the module made a change
- name: Plugin auth | Check that the module made a change (with hash string)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
- name: Plugin auth | Check that the expected plugin type is set (with hash string)
assert:
that:
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Get the MySQL version using the newly created creds
- name: Plugin auth | Get the MySQL version using the newly created creds
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_auth_string }}'
@ -56,27 +58,28 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
- name: Update the user with a different hash
- name: Plugin auth | Update the user with a different hash
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_hash_string: '{{ test_plugin_new_hash }}'
register: result
- name: Check that the module makes the change because the hash changed
- name: Plugin auth | Check that the module makes the change because the hash changed
assert:
that:
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Getting the MySQL info with the new password should work
- name: Plugin auth | Getting the MySQL info with the new password should work
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_new_auth_string }}'
@ -85,45 +88,46 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_new_auth_string }}
- include: utils/remove_user.yml user_name={{ test_user_name }}
# ============================================================
# Test plugin auth initially setting a hash and then switching to a plaintext auth string.
#
- name: Create user with plugin auth (with hash string)
- name: Plugin auth | Create user with plugin auth (with hash string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_hash_string: '{{ test_plugin_hash }}'
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\""
- name: Plugin auth | Get user information
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = '%'\""
register: show_create_user
- name: Check that the module made a change
- name: Plugin auth | Check that the module made a change (with hash string)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
- name: Plugin auth | Check that the expected plugin type is set (with hash string)
assert:
that:
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Get the MySQL version using the newly created creds
- name: Plugin auth | Get the MySQL version using the newly created creds
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_auth_string }}'
@ -132,43 +136,45 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
- name: Update the user with the same hash (no change expected)
- name: Plugin auth | Update the user with the same hash (no change expected)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_hash_string: '{{ test_plugin_hash }}'
register: result
# FIXME: on mariadb 10.2 there's always a change
- name: Check that the module doesn't make a change when the same hash is passed in
- name: Plugin auth | Check that the module doesn't make a change when the same hash is passed in
assert:
that:
- result is not changed
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Change the user using the same plugin, but switch to the same auth string in plaintext form
- name: Plugin auth | Change the user using the same plugin, but switch to the same auth string in plaintext form
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_auth_string: '{{ test_plugin_auth_string }}'
register: result
# Expecting a change is currently by design (see comment in source).
- name: Check that the module did not change the password
- name: Plugin auth | Check that the module did not change the password
assert:
that:
- result is changed
- name: Getting the MySQL info should still work
- name: Plugin auth | Getting the MySQL info should still work
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_auth_string }}'
@ -177,45 +183,46 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
- include: utils/remove_user.yml user_name={{ test_user_name }}
# ============================================================
# Test plugin auth initially setting a plaintext auth string and then switching to a hash.
#
- name: Create user with plugin auth (with auth string)
- name: Plugin auth | Create user with plugin auth (with auth string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_auth_string: '{{ test_plugin_auth_string }}'
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
- name: Plugin auth | Get user information(with auth string)
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'%'\""
register: show_create_user
- name: Check that the module made a change
- name: Plugin auth | Check that the module made a change (with auth string)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
- name: Plugin auth | Check that the expected plugin type is set (with auth string)
assert:
that:
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- test_plugin_type in show_create_user.stdout
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Get the MySQL version using the newly created creds
- name: Plugin auth | Get the MySQL version using the newly created creds
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_auth_string }}'
@ -224,42 +231,44 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
- name: Update the user with the same auth string
- name: Plugin auth | Update the user with the same auth string
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_auth_string: '{{ test_plugin_auth_string }}'
register: result
# This is the current expected behavior because there isn't a reliable way to hash the password in the mysql_user
# module in order to be able to compare this password with the stored hash. See the source for more info.
- name: The module should detect a change even though the password is the same
- name: Plugin auth | The module should detect a change even though the password is the same
assert:
that:
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Change the user using the same plugin, but switch to the same auth string in hash form
- name: Plugin auth | Change the user using the same plugin, but switch to the same auth string in hash form
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
plugin_hash_string: '{{ test_plugin_hash }}'
register: result
- name: Check that the module did not change the password
- name: Plugin auth | Check that the module did not change the password
assert:
that:
- result is not changed
- name: Get the MySQL version using the newly created creds
- name: Plugin auth | Get the MySQL version using the newly created creds
mysql_info:
login_user: '{{ test_user_name }}'
login_password: '{{ test_plugin_auth_string }}'
@ -268,44 +277,45 @@
filter: version
register: result
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
- include: utils/remove_user.yml user_name={{ test_user_name }}
# ============================================================
# Test plugin auth with an empty auth string.
#
- name: Create user with plugin auth (empty auth string)
- name: Plugin auth | Create user with plugin auth (empty auth string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
- name: Plugin auth | Get user information (empty auth string)
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'%'\""
register: show_create_user
- name: Check that the module made a change
- name: Plugin auth | Check that the module made a change (empty auth string)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
- name: Plugin auth | Check that the expected plugin type is set (empty auth string)
assert:
that:
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=% priv={{ test_default_priv_type }}
- name: Get the MySQL version using an empty password for the newly created user
- name: Plugin auth | Get the MySQL version using an empty password for the newly created user
mysql_info:
login_user: '{{ test_user_name }}'
login_password: ''
@ -315,12 +325,12 @@
register: result
ignore_errors: true
- name: Assert that mysql_info was successful
- name: Plugin auth | Assert that mysql_info was successful
assert:
that:
- result is succeeded
- name: Get the MySQL version using an non-empty password (should fail)
- name: Plugin auth | Get the MySQL version using an non-empty password (should fail)
mysql_info:
login_user: '{{ test_user_name }}'
login_password: 'some_password'
@ -330,91 +340,92 @@
register: result
ignore_errors: true
- name: Assert that mysql_info failed
- name: Plugin auth | Assert that mysql_info failed
assert:
that:
- result is failed
- name: Update the user without changing the auth mechanism
- name: Plugin auth | Update the user without changing the auth mechanism
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
host: '%'
plugin: '{{ test_plugin_type }}'
state: present
register: result
- name: Assert that the user wasn't changed because the auth string is still empty
- name: Plugin auth | Assert that the user wasn't changed because the auth string is still empty
assert:
that:
- result is not changed
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
- include: utils/remove_user.yml user_name={{ test_user_name }}
# ============================================================
# Test plugin auth switching from one type of plugin to another without an auth string or hash. The only other
# plugins that are loaded by default are sha2*, but these aren't compatible with pymysql < 0.9, so skip these tests
# for those versions.
#
- name: Test plugin auth switching which doesn't work on pymysql < 0.9
- name: Plugin auth | Test plugin auth switching which doesn't work on pymysql < 0.9
when:
- >
connector_name is not search('pymysql')
connector_name != 'pymysql'
or (
connector_name is search('pymysql')
and connector_ver is version('0.9', '>=')
connector_name == 'pymysql'
and connector_version is version('0.9', '>=')
)
block:
- name: Create user with plugin auth (empty auth string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
plugin: '{{ test_plugin_type }}'
priv: '{{ test_default_priv }}'
register: result
- name: Plugin auth | Create user with plugin auth (empty auth string)
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
plugin: '{{ test_plugin_type }}'
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Plugin auth | Get user information (empty auth string)
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Plugin auth | Check that the module made a change (empty auth string)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- name: Plugin auth | Check that the expected plugin type is set (empty auth string)
assert:
that:
- test_plugin_type in show_create_user.stdout
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }}
- name: Switch user to sha256_password auth plugin
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
plugin: sha256_password
priv: '{{ test_default_priv }}'
register: result
- name: Plugin auth | Switch user to sha256_password auth plugin
mysql_user:
<<: *mysql_params
name: '{{ test_user_name }}'
plugin: sha256_password
priv: '{{ test_default_priv }}'
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Plugin auth | Get user information (sha256_password)
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Plugin auth | Check that the module made a change (sha256_password)
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- name: Plugin auth | Check that the expected plugin type is set (sha256_password)
assert:
that:
- "'sha256_password' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
- include: utils/assert_user.yml user_name={{ test_user_name }} user_host=localhost priv={{ test_default_priv_type }}
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
# Cleanup
- include: utils/remove_user.yml user_name={{ test_user_name }}

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -1,2 +1,3 @@
---
dependencies:
- setup_mysql
- setup_controller

View file

@ -1,3 +1,4 @@
---
# test code to assert variables in mysql_variables module
# (c) 2014, Wayne Rosario <wrosario@ansible.com>
@ -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

View file

@ -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

View file

@ -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

View file

@ -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 != {}