Compare commits

...

56 commits
main ... 1.5.0

Author SHA1 Message Date
Markus Bergholz
8687e575d7
prepare community.mysql 1.5.0 (#505)
* prepare 1.4.10

* 1.5.0
2023-02-08 10:34:27 +01:00
patchback[bot]
cf25d85e49
[PR #497/a5f3296d backport][stable-1] mysql_info - Add connector_name and connector_version to returned value (#498)
* mysql_info - Add connector_name and connector_version to returned value (#497)

* Add methods to retrieve connector name and version
* Document that mysqlclient is also named MySQLdb
* Document version_added
* Add connector name and version in the returned block
* Cut condition to display any name that is return

In case of MySQLdb is renamed in mysqlclient. In that case, the
integration tests will catch this the day we update the connector
version.

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
(cherry picked from commit a5f3296d73)

* Cut fragment not relevant to the collection usage

* Updated version_added for stable-1

---------

Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me>
2023-02-01 09:47:44 +01:00
patchback[bot]
cb323da665
README: improve Matrix badge (#494) (#495)
* README: improve Matrix badge

* Add text

(cherry picked from commit 3229ce4e55)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2023-01-26 09:11:07 +01:00
Andrew Klychkov
963e042edd
491-CI-fix-tarball-download (#491) (#493)
* Fix mariadb test setup

* Update mysql src URL

* Add changelog fragment

* Update 491_fix_download_url.yaml

Sanity test failed because minor_changes in not an element of a list.

* Fix casing

Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me>
(cherry picked from commit 00fa058a18)

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@futurice.com>
2023-01-25 10:56:39 +01:00
patchback[bot]
a026d60f84
README: update Matrix badge (#485) (#487)
(cherry picked from commit 4ad71775a6)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2023-01-16 13:26:20 +01:00
Andrew Klychkov
43a8037232
Docs: change yes/no to true/false (#480) (#482)
(cherry picked from commit 3ff1fad5f3)
2023-01-03 12:56:33 +01:00
patchback[bot]
43e688a37a
CI: add PR change detection (#473) (#477)
(cherry picked from commit eade7ec1f0)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-12-09 16:37:56 +01:00
patchback[bot]
878dc5794a
Add fixed version of Ubuntu (#470) (#471)
This is because ubuntu-latest link to ubuntu-22.04 which includes
cgroup-v2. I thinks our tests fails because of that. See
https://github.com/ansible-collections/news-for-maintainers/issues/28
for more information.

(cherry picked from commit 4dac66382a)

Co-authored-by: Laurent Indermühle <laurent.indermuehle@pm.me>
2022-12-07 16:45:54 +01:00
Laurent Indermühle
85a63511b6
Backport/stable 1/pr 452 (#464)
* Sync GHA workflow w/ the collection template (#452)

* Sync GHA workflow w/ the collection template

* Drop the trailing pre-cmd semicolon

* Recover missing `-e` flag of `sed`

* Use relative paths for version configs

* Unquote `env.connector_version_file`

* Use string formatting to fix the substitution problem

(cherry picked from commit 8107530744)
(cherry picked from commit 704a0cea6a)

* Backport mysql_version_parts variable assignation

(cherry picked from commit 79046a88cb)
(cherry picked from commit a59d95501e)

* Add changelog fragment

(cherry picked from commit 26ecd68801)

* Backport flags and variables to differentiate MariaDB from MySQL setup

(cherry picked from commit b4303511d5)

* Backport issue-28 check for tls support

(cherry picked from commit efde607d25)

* Backport tls_requirements simplified and deduplified tests

(cherry picked from commit ac5a339644)

Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
2022-11-10 15:00:42 +01:00
patchback[bot]
fadbd30572
README: Add matrix room + badge (#459) (#460)
* README: Add matrix room + badge

* improve

(cherry picked from commit 09e02320fd)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-11-01 13:27:51 +01:00
patchback[bot]
2020870155
* add socket option suggestion in documentation (#437) (#454)
* * add `socket` option suggestion in documentation

* white space fix

* * move first two at the end

(cherry picked from commit b9a6ec4f7d)

Co-authored-by: Gabriel PREDA <eRadical@users.noreply.github.com>
2022-10-04 13:29:25 +02:00
patchback[bot]
40da237de7
CI: add stable-2.14 to test matrix (#449) (#451)
(cherry picked from commit b8e2c02e89)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-09-23 07:06:15 +02:00
patchback[bot]
786470058c
Fix: devel requires python 3.9 in roles CI (#444) (#447)
* Fix: devel requires python 3.9

Package 'ansible-core' requires a different Python: 3.8.13 not in '>=3.9'

* Exclude older version of Ansible when testing Python 3.9

(cherry picked from commit 2cd29207f3)

Co-authored-by: R.Sicart <roger.sicart@gmail.com>
2022-09-16 16:15:25 +02:00
patchback[bot]
d363315ecb
Combine REVIEW_CHECKLIST.md and CONTRIBUTING.md and fix links (#432) (#440)
(cherry picked from commit ea73d408c3)

Co-authored-by: Maxwell G <9920591+gotmax23@users.noreply.github.com>
2022-09-06 09:48:56 +02:00
Laurent Indermühle
275d85067a
[PR #427/0a68bb27 backport][stable-1] CI is changed (#428)
* Is changed (#427)

* Refactor tests to use "is" and "is not" changed

* Refactor tests to use is succeeded or is failed

* Reformat indentation

* Add filter "bool" to prevent issues

(cherry picked from commit 0a68bb270f)

* Fix error message verification

I don't know why this works on main, but in stable-1, the error message
is "invalid privileges string: Invalid privileges specified:
frozenset({'INVALID'})"

* Add filter for test that won't work with mariadb

* Refactor test in their own file instead of main

* Add db_names dict

* Fix registered variable name

* Add missing fact

* Add test databases cleanup

* Cut tests for unsupported db name (%)

* Add missing default vars to tests db_formats

* Backport small diff from main
2022-08-29 10:19:31 +02:00
Andrew Klychkov
c199000eee
Docs: add info how to cope with a protocol-related connection error using login_unix_socket argument (#420) (#431)
(cherry picked from commit f1d63e3fc8)
2022-08-26 13:41:06 +02:00
Laurent Indermühle
108c4ae729
Port stable 1 ci changes (#423) (#425)
* Add changes from stable-1 integrations tests (PR 418)

* Refactor to use connectors' info declared in setup_mysql

* Fix 2nd replication stop marked changed by mysqlclient

(cherry picked from commit 61586ae4cc)
2022-08-22 12:36:44 +02:00
Laurent Indermühle
4cfdbe64a3
MAINTAINERS file: add a new maintainer (#419) (#422)
(cherry picked from commit 057f817111)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-08-13 22:06:12 +02:00
Laurent Indermühle
836a1ce048
[PR #416/97318559 backport][stable-1] Fix ci python requirements (#418)
* :Fix ci python requirements (#416)

* Add matrix for python and ansible-core versions for sanity tests

* Add python 3.9 to integrations tests

* Add python 3.9 to unit tests

* Reformat sort by python version first

(cherry picked from commit 97318559e5)

* Fix string to int comparison error 1292

* Fix assert expected changed value

* Cut assertion that is incorrect

With both connectors, and only in stable-1 apparently, the test is
always failed.

* Fix bool comparison

* Revert separated tests for both connectors

* Refactor test using connector.name variable

* Refactor filtering of tasks using connector's vars sets during setup

* Fix "command not found" and "database doesn't exists"

* Fix assertion by not running on failing connectors

* Fix missing package when using sha256_password with MySQL 8
2022-08-12 16:51:40 +02:00
Laurent Indermühle
41e7ce5aaa
Update galaxy.yml to the next expected version (#412) 2022-08-03 10:26:26 +02:00
Laurent Indermühle
99548e10cb
Release 1.4.8 commit (#410) 2022-08-02 10:08:19 +02:00
patchback[bot]
6ebf59e234
README: update MariaDB versions we test against (#404) (#406)
(cherry picked from commit 6f87620d9b)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-06-24 15:07:27 +02:00
patchback[bot]
97be51ef45
Note added regarding the default config file, ~/.my.cnf (#400) (#402)
* Note added for https://github.com/ansible-collections/community.mysql/issues/394

* Update config file notes as discussed

* Update plugins/doc_fragments/mysql.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
(cherry picked from commit 0df46e0e67)

Co-authored-by: Chris Croome <chris@webarchitects.co.uk>
2022-06-17 08:27:00 +02:00
Andrew Klychkov
d8ab933d79
Update licensing information (#392) 2022-06-03 16:28:29 +02:00
Andrew Klychkov
949cb0c1dd
Release 1.4.7 commit (#387) 2022-06-02 08:15:26 +02:00
patchback[bot]
89eb2d2fea
Changed += to append because cmd is a list (#377) (#386)
Using += on a list cause some problems druing creation of mysql command:
/usr/bin/mysql   - - u s e r = r o o t   - - p a s s w o r d = ' ' --socket=/run/mysqld/mysqld.sock

(cherry picked from commit 2e9d50f274)

Co-authored-by: Maciej <moledzki@users.noreply.github.com>
2022-06-01 07:58:16 +02:00
hubiongithub
4d4a5f2a02
merge into stable1 (#383)
* PR379 merge

* Update plugins/modules/mysql_user.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
2022-05-31 17:43:15 +02:00
Andrew Klychkov
f7677aa05b
[stable-1] mysql_query: fix false change reports when IF NOT EXISTS clause is used (#375)
* mysql_query: fix false change reports when IF NOT EXISTS clause is used (#322)

* mysql_query: fix false change reports when IF NOT EXISTS clause is used

* Fix

* Fix doc, add fragment

* Improve doc

(cherry picked from commit 647461010d)

* Fix tests
2022-05-26 08:41:21 +02:00
Andrew Klychkov
0921d4eef5
Release 1.4.6 commit (#361) 2022-05-17 12:08:28 +02:00
Felix Fontein
f4736770e3
Add PSF-license.txt file (#356) (#359)
* Add PSF-license.txt file.

* Update with actual CPython 3.9.5 license.

(cherry picked from commit b2e476cb1a)
2022-05-17 08:24:07 +02:00
Andrew Klychkov
3bb7b00497
Release 1.4.5 commit (#353) 2022-05-13 09:07:25 +02:00
Andrew Klychkov
393023eb07
[stable-1] mysql_user: fix parsing privs when a user has roles assigned to it (#346)
* mysql_user: fix parsing privs when a user has roles assigned to it

* Fix CI

* Fix CI
2022-05-12 15:19:20 +02:00
Andrew Klychkov
256817ca32
Drop support for Ansible 2.9 and ansible-base 2.10 (#347) 2022-05-12 14:11:36 +02:00
patchback[bot]
a2a4a1ff61
Move CHANGELOG.rst at top level (#349) (#351)
(cherry picked from commit f57ed38beb)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-05-12 11:53:46 +02:00
Andrew Klychkov
b730cd6675
mysql_user: added flush privileges to write dynamic privs into db (#340) 2022-04-29 17:52:07 +02:00
Andrew Klychkov
2a57a4d659
CI: add testing against ansible-core 2.13 (#328)
Co-authored-by: R.Sicart <roger.sicart@gmail.com>
2022-04-03 08:10:42 +02:00
Andrew Klychkov
278337d34f
[stable-1] Backports (#325)
* Clarified error message about missing python modules (#279)

* Clarified error message about missing python modules, and tweak documentation to suggest overriding interpreter.

* Mention mysqlclient as another option

* Correct mysqlclient suggestions from python2 to python3

Co-authored-by: Matthew Exon <git.mexon@spamgourmet.com>
(cherry picked from commit 82baf7508c)

* Copy ignore-2.13.txt to ignore-2.14.txt (#323)

* Copy ignore-2.13.txt to ignore-2.14.txt

* Fix sanity

(cherry picked from commit c16b2428e8)

Co-authored-by: Matthew Exon <github2.mexon@neverbox.com>
2022-04-02 17:33:52 +02:00
patchback[bot]
d5a1e3639a
mysql_user: clarify behavior of priv parameter (#319) (#320)
(cherry picked from commit 5afae459dc)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-03-25 12:33:01 +01:00
patchback[bot]
bfcf89073a
Fix roles CI (#316) (#318)
(cherry picked from commit e6e661b87f)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2022-03-24 06:55:08 +01:00
patchback[bot]
15ee80b57c
Setup patchback bot config file (resolves #310) (#311) (#313)
(cherry picked from commit 55458f5b0b)

Co-authored-by: R.Sicart <roger.sicart@gmail.com>
2022-03-17 11:19:01 +01:00
Andrew Klychkov
59d411ac82
Add IF EXISTS clause to DROP USER statement (#309) 2022-03-15 15:43:09 +01:00
Andrew Klychkov
b0de252ce2
Update requirements (#302) 2022-03-15 13:53:20 +01:00
Andrew Klychkov
96a255c00a
[stable-1] Enable and fix integration tests for devel (#298)
* Enable and fix integration tests for devel

* Add exclusions
2022-03-14 11:51:54 +01:00
Andrew Klychkov
f46b84e670
Release 1.4.4 commit (#277) 2022-01-18 11:05:37 +01:00
Andrew Klychkov
9386045797
[stable-1] Use vendored version of distutils.version (#274)
* Prepare for distutils.version being removed in Python 3.12 (#267)

* Prepare for distutils.version being removed in Python 3.12

* Update plugins/module_utils/version.py

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit d9e12b85ad)

* Use vendored version of distutils.version (#269)

* Use vendored version of distutils.version

* Correct fragment

* Update plugins/module_utils/version.py

Co-authored-by: Felix Fontein <felix@fontein.de>

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 9c575b4762)

* Add ignore-2.13.txt
2022-01-18 10:53:09 +01:00
Andrew Klychkov
ace830ef56
Release 1.4.3 commit (#222) 2021-09-23 14:29:24 +02:00
Andrew Klychkov
e5919428f1
Update README.md (#216) (#221)
(cherry picked from commit 4de0e25ea0)
2021-09-23 14:07:17 +02:00
Andrew Klychkov
dbcc7e7e60
[stable-1] mysql_info: fix TypeError failure when there are databases that do not contain tables (#209)
* mysql_info: fix TypeError failure when there are databases that do not contain tables (#205)

* mysql_info: fix TypeError failure when there are databases that do not contain tables

* Add changelog fragment

(cherry picked from commit a1f419d541)

* Fix sanity errors
2021-08-20 09:50:34 +02:00
Andrew Klychkov
f49206d3b3
Release 1.4.2 commit (#198) 2021-08-11 08:38:59 +02:00
Andrew Klychkov
64b06aa543
mysql_query: correctly reflect changed status in replace statements (#193) (#197)
* mysql_query: correctly reflect changed status in replace statements.

* Fix the wrong indent.

(cherry picked from commit 9055bb4c8c)

Co-authored-by: Tong He <68936428+unnecessary-username@users.noreply.github.com>
2021-08-10 15:38:37 +02:00
Andrew Klychkov
9c17158802
[stable-1] Doc commit backport (#196)
* Add CONTRIBUTORS file (#166)

(cherry picked from commit ac927fdb08)

* Add documentation for privs with functions and procedures (#169)

(cherry picked from commit 6bce48e771)

* Update README.md (#168)

* Update README.md

* Fix

* Add MAINTAINERS file

(cherry picked from commit 479edd81d1)

* Improve wording in README (#170)

* Improve wording in README

* Update README.md

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

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@tiriel.eu>
(cherry picked from commit c909aa2182)

* Update REVIEW_CHECKLIST.md (#171)

(cherry picked from commit 2236110bae)

* README: add a note how people can complain (#172)

* README: add a note how people can complain

* Change

* Improve

* Update README.md

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

Co-authored-by: Jorge Rodriguez (A.K.A. Tiriel) <jorge.rodriguez@tiriel.eu>
(cherry picked from commit be4e84a92a)

* README: fix typos (#174)

(cherry picked from commit 2a80c301a6)

* README.md: Add link to IRC (#175)

(cherry picked from commit 3335a95ba5)

* README.md, CONTRIBUTING.md: add links to the Maintainer guidelines (#179)

(cherry picked from commit 8fad3f85b8)

* Update README (#181)

(cherry picked from commit 6d9288d19b)

* Update README.md (#183)

* Update README.md

* Change IRC ref

(cherry picked from commit 69012a2eb9)

* README: fix link (#184)

(cherry picked from commit 8ab6ea7714)

* README: fix the channel name (#185)

(cherry picked from commit cd759924fd)

* CONTRIBUTING.md: replace the content with a link to Ansible contributing guidelines (#187)

(cherry picked from commit 56a214885a)

* Update README (#186)

* Update README

* Fix

* Fix

* Fix

* Fix

* Add Libera.Chat link

(cherry picked from commit adb201a795)

* fix typo (#190)

"optoin" -> "option"

(cherry picked from commit 596ba0cedb)

* Update README.md (#191)

* Update README.md

* Update README.md

(cherry picked from commit 6f02cb266a)

* Add MAINTAINING.md, update README.md (#192)

(cherry picked from commit 0fabb2b77a)

Co-authored-by: Alexander Skiba <ghostlyrics@gmail.com>
Co-authored-by: Baptiste Mille-Mathias <baptiste.millemathias@gmail.com>
2021-08-10 14:33:56 +02:00
Andrew Klychkov
d200481305
Update galaxy.yml (#160) 2021-04-23 16:44:33 +02:00
Andrew Klychkov
b3a83aa0a3
Release 1.4.1 commit (#159) 2021-04-23 15:59:12 +02:00
Andrew Klychkov
fe8f3662eb
mysql: revert changes made in PR 116 (#153) (#156)
* mysql: revert changes made in PR 116

* Add changelog fragment

* Fix CI

* Fix CI

* Fix CI

* Update CI

* Fix CI

(cherry picked from commit 738343d64c)
2021-04-23 14:08:49 +02:00
Andrew Klychkov
59cbe5ffe3 Release 1.4.0 2021-04-16 08:53:51 +02:00
Andrew Klychkov
d517d658a1 Update galaxy.yml 2021-04-16 07:08:18 +02:00
79 changed files with 2535 additions and 985 deletions

5
.github/patchback.yml vendored Normal file
View file

@ -0,0 +1,5 @@
---
backport_branch_prefix: patchback/backports/
backport_label_prefix: backport-
target_branch_prefix: stable-
...

View file

@ -15,97 +15,97 @@ on:
env:
mysql_version_file: "./ansible_collections/community/mysql/tests/integration/targets/setup_mysql/defaults/main.yml"
connector_version_file: "./ansible_collections/community/mysql/tests/integration/targets/setup_mysql/vars/main.yml"
mysql_version_file: "tests/integration/targets/setup_mysql/defaults/main.yml"
connector_version_file: "tests/integration/targets/setup_mysql/vars/main.yml"
jobs:
sanity:
name: "Sanity (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }})"
runs-on: ubuntu-latest
name: "Sanity (Ansible: ${{ matrix.ansible }})"
runs-on: ubuntu-20.04
strategy:
matrix:
ansible:
- stable-2.9
- stable-2.10
- stable-2.11
- stable-2.12
- stable-2.13
- stable-2.14
- devel
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Perform sanity testing
uses: ansible-community/ansible-test-gh-action@release/v1
with:
path: ansible_collections/community/mysql
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install ansible-base (${{ matrix.ansible }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
- name: Run sanity tests
run: ansible-test sanity --docker -v --color
working-directory: ./ansible_collections/community/mysql
ansible-core-version: ${{ matrix.ansible }}
testing-type: sanity
pull-request-change-detection: true
integration:
name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.mysql }}, Connector: ${{ matrix.connector }})"
runs-on: ubuntu-latest
name: "Integration (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.db_engine_version }}, Connector: ${{ matrix.connector }})"
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
mysql:
- 5.7.31
- 8.0.22
db_engine_version:
- mysql_5.7.31
- mysql_8.0.22
ansible:
- stable-2.9
- stable-2.10
- stable-2.11
- stable-2.12
- stable-2.13
- stable-2.14
- devel
python:
- 3.6
- 3.8
- 3.9
connector:
- pymysql==0.7.10
- pymysql==0.9.3
- mysqlclient==2.0.1
exclude:
- mysql: 8.0.22
- db_engine_version: mysql_8.0.22
connector: pymysql==0.7.10
- python: 3.6
ansible: stable-2.12
- python: 3.6
ansible: stable-2.13
- python: 3.6
ansible: stable-2.14
- python: 3.6
ansible: devel
- python: 3.8
ansible: stable-2.13
- python: 3.8
ansible: stable-2.14
- python: 3.8
ansible: devel
- python: 3.9
ansible: stable-2.12
steps:
- name: Check out code
uses: actions/checkout@v2
- name: >-
Perform integration testing against
Ansible version ${{ matrix.ansible }}
under Python ${{ matrix.python }}
uses: ansible-community/ansible-test-gh-action@release/v1
with:
path: ansible_collections/community/mysql
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install ansible-base (${{ matrix.ansible }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
- name: Set MySQL version (${{ matrix.mysql }})
run: "sed -i 's/^mysql_version:.*/mysql_version: \"${{ matrix.mysql }}\"/g' ${{ env.mysql_version_file }}"
- name: Set Connector version (${{ matrix.connector }})
run: "sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }}"
- name: Run integration tests
run: ansible-test integration --docker -v --color --retry-on-error --continue-on-error --python ${{ matrix.python }} --diff --coverage
working-directory: ./ansible_collections/community/mysql
- name: Generate coverage report.
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
working-directory: ./ansible_collections/community/mysql
- uses: codecov/codecov-action@v1
with:
fail_ci_if_error: false
ansible-core-version: ${{ matrix.ansible }}
pre-test-cmd: >-
DB_ENGINE=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $1}');
DB_VERSION=$(echo '${{ matrix.db_engine_version }}' | awk -F_ '{print $2}');
DB_ENGINE_PRETTY=$([[ "${DB_ENGINE}" == 'mysql' ]] && echo 'MySQL' || echo 'MariaDB');
>&2 echo Matrix factor for the DB is ${{ matrix.db_engine_version }}...;
>&2 echo Setting ${DB_ENGINE_PRETTY} version to ${DB_VERSION}...;
sed -i -e "s/^${DB_ENGINE}_version:.*/${DB_ENGINE}_version: $DB_VERSION/g" '${{ env.mysql_version_file }}';
if [[ ${{ matrix.db_engine_version }} == mariadb* ]];
then
echo Set MariaDB install flag...; sed -i -e "s/^mariadb_install: false/mariadb_install: true/g" '${{ env.mysql_version_file }}';
echo Set MariaDB v10.8.3 URL sub dir...; sed -i -e "s/^mariadb_url_subdir:.*/mariadb_url_subdir: linux-systemd/g" '${{ env.connector_version_file }}';
fi;
>&2 echo Setting Connector version to ${{ matrix.connector }}...;
sed -i 's/^python_packages:.*/python_packages: [${{ matrix.connector }}]/' ${{ env.connector_version_file }}
target-python-version: ${{ matrix.python }}
testing-type: integration
pull-request-change-detection: true
units:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
name: Units (Ⓐ${{ matrix.ansible }})
strategy:
# As soon as the first unit test fails,
@ -113,36 +113,30 @@ jobs:
fail-fast: true
matrix:
ansible:
- stable-2.9
- stable-2.10
- stable-2.11
- stable-2.12
- stable-2.13
- stable-2.14
- devel
python:
- 3.8
- 3.9
exclude:
- python: 3.8
ansible: stable-2.13
- python: 3.8
ansible: stable-2.14
- python: 3.8
ansible: devel
- python: 3.9
ansible: stable-2.12
steps:
- name: Check out code
uses: actions/checkout@v2
- name: >-
Perform unit testing against
Ansible version ${{ matrix.ansible }}
uses: ansible-community/ansible-test-gh-action@release/v1
with:
path: ./ansible_collections/community/mysql
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install ansible-base (${{matrix.ansible}})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
# Run the unit tests
- name: Run unit test
run: ansible-test units -v --color --docker --coverage
working-directory: ./ansible_collections/community/mysql
# ansible-test support producing code coverage date
- name: Generate coverage report
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
working-directory: ./ansible_collections/community/mysql
# See the reports at https://codecov.io/gh/GITHUBORG/REPONAME
- uses: codecov/codecov-action@v1
with:
fail_ci_if_error: false
ansible-core-version: ${{ matrix.ansible }}
target-python-version: ${{ matrix.python }}
testing-type: units
pull-request-change-detection: true

View file

@ -14,7 +14,7 @@ on:
jobs:
molecule:
name: "Molecule (Python: ${{ matrix.python }}, Ansible: ${{ matrix.ansible }}, MySQL: ${{ matrix.mysql }})"
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
env:
PY_COLORS: 1
ANSIBLE_FORCE_COLOR: 1
@ -23,14 +23,31 @@ jobs:
mysql:
- 2.0.12
ansible:
- stable-2.9
### it looks like there's errors for 2.10+ with ansible-lint (https://github.com/ansible/ansible-lint/pull/878)
### and molecule (_maybe_ relating to https://github.com/ansible-community/molecule/pull/2547)
# - stable-2.10
# - devel
- stable-2.11
- stable-2.12
- stable-2.13
- devel
python:
- 2.7
- 3.6
- 3.8
- 3.9
exclude:
- python: 3.6
ansible: stable-2.12
- python: 3.6
ansible: stable-2.13
- python: 3.6
ansible: devel
- python: 3.8
ansible: stable-2.11
- python: 3.8
ansible: stable-2.13
- python: 3.8
ansible: devel
- python: 3.9
ansible: stable-2.11
- python: 3.9
ansible: stable-2.12
steps:
@ -44,7 +61,7 @@ jobs:
with:
python-version: ${{ matrix.python }}
- name: Install ansible-base (${{ matrix.ansible }})
- name: Install ansible-core (${{ matrix.ansible }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
- name: Install molecule and related dependencies

4
.gitignore vendored
View file

@ -1,5 +1,6 @@
/tests/output/
/changelogs/.plugin-cache.yaml
*.swp
# Byte-compiled / optimized / DLL files
__pycache__/
@ -133,3 +134,6 @@ dmypy.json
# MacOS
.DS_Store
# IntelliJ IDEA or PyCharm
.idea/

View file

@ -5,6 +5,177 @@ Community MySQL Collection Release Notes
.. contents:: Topics
v1.5.0
=======
Release Summary
---------------
This is a minor release of the ``community.mysql`` collection.
This changelog contains all changes to the modules and plugins in this collection
that have been made after the previous release.
Minor Changes
-------------
- mysql_info - add ``connector_name`` and ``connector_version`` to returned values (https://github.com/ansible-collections/community.mysql/pull/497).
v1.4.8
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.7.
Bugfixes
--------
- Include ``simplified_bsd.txt`` license file for various module utils.
v1.4.7
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.6.
Bugfixes
--------
- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause is used (https://github.com/ansible-collections/community.mysql/issues/268).
- mysql_user - fix logic when ``update_password`` is set to ``on_create`` for users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334). The ``on_create`` sets ``password`` to None for old mysql_native_authentication but not for authentiation methods which uses the ``plugin*`` arguments. This PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``, ``plugin_auth_string`` to None in the list of arguments to change
v1.4.6
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.5.
Bugfixes
--------
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
v1.4.5
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.4.
Major Changes
-------------
- The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base 2.10``. While we take no active measures to prevent usage and there are no plans to introduce incompatible code to the modules, we will stop testing against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be End of Life and if you are still using them, you should consider upgrading to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible (https://github.com/ansible-collections/community.mysql/pull/343).
Bugfixes
--------
- mysql_user - fix missing dynamic privileges after revoke and grant privileges to user (https://github.com/ansible-collections/community.mysql/issues/120).
- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231).
- mysql_user - fix the possibility for a race condition that breaks certain (circular) replication configurations when ``DROP USER`` is executed on multiple nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin: no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287).
v1.4.4
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.3.
Bugfixes
--------
- Collection core functions - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269).
v1.4.3
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.2.
Bugfixes
--------
- mysql_info - fix TypeError failure when there are databases that do not contain tables (https://github.com/ansible-collections/community.mysql/issues/204).
v1.4.2
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.1.
Minor Changes
-------------
- mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193).
v1.4.1
======
Release Summary
---------------
This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection
that have been added after the release of ``community.mysql`` 1.4.0.
Bugfixes
--------
- mysql - revert changes of connector arguments made in pull request 116 causing the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116).
v1.4.0
======
Release Summary
---------------
This is the minor release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection
that have been added after the release of ``community.mysql`` 1.3.0.'
Major Changes
-------------
- mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires`` option in ``community.mysql`` 2.0.0 and support will be dropped altogether in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121).
Minor Changes
-------------
- mysql module utils - change deprecated connection parameters ``passwd`` and ``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116).
- mysql_collection - introduce codebabse split to handle divergences between MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103).
- mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114).
- mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101).
Bugfixes
--------
- mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105).
v1.3.0
======

View file

@ -1,200 +1,5 @@
# Contributing
We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our contributions and interactions within this repository.
Refer to the [Ansible Contributing guidelines](https://docs.ansible.com/ansible/devel/community/index.html) to learn how to contribute to this collection.
If you are a committer, also refer to the [Ansible committer guidelines](https://docs.ansible.com/ansible/devel/community/committer_guidelines.html).
## Issue tracker
Whether you are looking for an opportunity to contribute or you found a bug and already know how to solve it, please go to the [issue tracker](https://github.com/ansible-collections/community.mysql/issues).
There you can find feature ideas to implement, reports about bugs to solve, or submit an issue to discuss your idea before implementing it which can help choose a right direction at the beginning of your work and potentially save a lot of time and effort.
Also somebody may already have started discussing or working on implementing the same or a similar idea,
so you can cooperate to create a better solution together.
## Open pull requests
Look through currently [open pull requests](https://github.com/ansible-collections/community.mysql/pulls).
You can help by reviewing them. Reviews help move pull requests to merge state. Some good pull requests cannot be merged only due to a lack of reviews. And it is always worth saying that good reviews are often more valuable than pull requests themselves. For more information how to provide a good review, refer to the [review checklist](REVIEW_CHECKLIST.md).
Also, consider taking up a valuable, reviewed, but abandoned pull request which you could politely ask the original authors to complete yourself.
## Discussions
For open questions, broad suggestions, and other comments that will not typically fit in the scope of an issue or pull request, [discussions](https://github.com/ansible-collections/community.mysql/discussions) are available. That section provides a place to have a more open and informal conversation about any and all things related to this collection, included but not limited to future development plans, functionality explanations and feature proposals that are not yet fleshed out enough for an issue of their own.
## Looking for an idea to implement
First, see the paragraphs above.
If you came up with a new feature, it is always worth creating an issue
before starting to write code to discuss the idea with the community first.
If you are going to implement the feature yourself, say it in the issue explicitly to avoid working in parallel with somebody else.
## Step-by-step guide how to get into development quickly
We assume that you use Linux as a work environment (you can use a virtual machine as well) and have `git` installed.
1. If possible, make sure that you have installed and started `docker`. While you can also run tests without docker, this makes it a lot easier since you do not have to install the precise requirements, and tests are running properly isolated and in the exact same environments as in CI. You often can also use `podman` with the `docker` executable shim, so if you have that you probably do not need to install `docker`.
2. Clone the [ansible-core](https://github.com/ansible/ansible) repository:
```bash
git clone https://github.com/ansible/ansible.git
```
Instead of installing ansible-core from source, you can also work with an already existing installation of Ansible, ansible-base or ansible-core. Simply skip steps 2 and 3 in that case.
3. Go to the cloned repository and prepare the environment:
```bash
cd ansible && source hacking/env-setup
pip install -r requirements.txt
cd ~
```
4. Create the following directories in your home directory:
```bash
mkdir -p ~/ansible_collections/community/mysql
```
5. Fork the `community.mysql` repository through the GitHub web interface.
6. Clone the forked repository from your profile to the created path:
```bash
git clone https://github.com/YOURACC/community.mysql.git ~/ansible_collections/community/mysql
```
If you prefer to use the SSH protocol:
```bash
git clone git@github.com:YOURACC/community.mysql.git ~/ansible_collections/community/mysql
```
7. Go to your new cloned repository.
```bash
cd ~/ansible_collections/community/mysql
```
8. Be sure you are in the main branch:
```bash
git status
```
9. Show remotes. There should be the `origin` repository only:
```bash
git remote -v
```
10. Add the `upstream` repository:
```bash
git remote add upstream https://github.com/ansible-collections/community.mysql.git
```
11. Update your local `main` branch:
```bash
git fetch upstream
git rebase upstream/main
```
12. Create a branch for your changes:
```bash
git checkout -b name_of_my_branch
```
13. We recommend you start with writing integration tests if applicable.
Note: If there are any difficulties with writing the tests or you are not sure if the case can be covered, feel free to skip this step.
If needed, other contributors can help you with it later.
All integration tests are stored in `tests/integration/targets` subdirectories.
Go to the subdirectory containing the name of module you are going to change.
For example, if you are fixing the `mysql_user` module, its tests are in `tests/integration/targets/test_mysql_user/tasks`.
The `main.yml` file holds test tasks and includes other test files.
Look for a suitable test file to integrate your tests or create and include a dedicated test file.
You can use one of the existing test files as a draft.
When fixing a bug, write a task which reproduces the bug from the issue.
Put the reported case in the tests, then run integration tests with the following command:
```bash
ansible-test integration test_mysql_user --docker -vvv
```
If the tests do not want to run, first, check you complete step 3 of this guide.
If the tests ran successfully, there are usually two possible outcomes:
a) If the bug has not appeared and the tests have passed successfully, ask the reporter to provide more details. The bug can be not a bug actually or can relate to a particular software version used or specifics of local environment configuration.
b) The bug has appeared and the tests has failed as expected showing the reported symptoms.
14. Fix the bug.
15. Run `flake8` against a changed file. If it is `plugins/modules/mysql_user.py`:
```bash
flake8 plugins/modules/mysql_user.py
```
It is worth installing and running `flake8` against the changed file(s) first.
It shows unused imports, which is not shown by sanity tests (see the next step), as well as other common issues.
Optionally, you can use the `--max-line-length=160` command-line argument.
16. Run sanity tests:
```bash
ansible-test sanity plugins/modules/mysql_user.py --docker
```
If they failed, look at the output carefully - it is usually very informative and helps to identify a problem line quickly.
Sanity failings usually relate to wrong code and documentation formatting.
17. Run integration tests:
```bash
ansible-test integration test_mysql_user --docker -vvv
```
There are two possible outcomes:
a) They have failed. Look at the output of the command.
Fix the problem place in the code and run again.
Repeat the cycle until the tests pass.
b) They have passed. Remember they failed originally? Our congratulations! You have fixed the bug.
18. Commit your changes with an informative but short commit message:
```bash
git add /path/to/changed/file
git commit -m "mysql_user: fix crash when ..."
```
19. Push the branch to the `origin` (your fork):
```bash
git push origin name_of_my_branch
```
20. Go to the `upstream` (http://github.com/ansible-collections/community.mysql).
21. Go to `Pull requests` tab and create a pull request.
GitHub is tracking your fork, so it should see the new branch in it and automatically offer
to create a pull request. Sometimes GitHub does not do it and you should click the `New pull request` button yourself.
Then choose `compare across forks` under the `Compare changes` title.
Choose your repository and the new branch you pushed in the right drop-down list.
Confirm. Fill out the pull request template with all information you want to mention.
Put "Fixes + link to the issue" in the pull request's description.
Put "[WIP] + short description" in the pull request's title. It's often a good idea to mention the name of the module/plugin you are modifying at the beginning of the description.
Click `Create pull request`.
22. Add a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#changelogs) to the `changelog/fragments` directory. It will be published in release notes, so users will know about the fix.
Commit and push it:
```bash
git add changelog/fragments/myfragment.yml
git commit -m "Add changelog fragment"
git push origin name_of_my_branch
```
23. The CI tests will run automatically on Red Hat infrastructure after every commit.
You will see the CI status in the bottom of your pull request.
If they are green, remove "[WIP]" from the title. Mention the issue reporter in a comment and let contributors know that the pull request is "Ready for review".
24. Wait for reviews. You can also ask for review on IRC in the #ansible-community channel.
25. If the pull request looks good to the community, committers will merge it.
For details, refer to the [Ansible developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html).
If you find any inconsistencies or places in this document which can be improved, feel free to raise an issue or pull request to fix it.
Refer to the [review checklist](https://docs.ansible.com/ansible/devel/community/collection_contributors/collection_reviewing.html) when triaging issues or reviewing PRs.

274
CONTRIBUTORS Normal file
View file

@ -0,0 +1,274 @@
116davinder
20
28
29
4
4n70w4
abadger
abondis
acozine
adamchainz
adq
Akasurde
Alexander198961
alustenberg
aminvakil
amitk79
amree
Andersson007
andrewhowdencom
ansibot
anthonyxpalermo
antonioribeiro
apollo13
aquach
arcmop
asad-at-srt
AshDevilRed
aurimasl
axelll
axisK
azielke
baldpale
banyek
BarbzYHOOL
Berbe
bjne
bmalynovytch
bmildren
boreal321
brutus
burner1024
calfonso
candeira
caphrim007
cdalbergue
checkphi
chrismeyersfsu
ChristopherGAndrews
cmodijk
codeaken
codebymikey
coreylane
CormacBracken
cosmix
cptMikky
crashes
dagwieers
damianmoore
Davidffry
denisemauldin
diclophis
d-lee
dmp1ce
dnelson
dramaley
drybjed
drzraf
DSpeichert
dungdm93
dwagelaar
dylanjbarth
einarc
E-M
eowin
Ernest0x
esamattis
Everspace
F21
faitno
felixfontein
flatrocks
fourjay
fraff
g00fy-
geerlingguy
georgeOsdDev
ghjm
ghost
giacmir
giorgio-v
gkoller
gottwald
gstorme
gundalow
hansbaer
hchargois
hluaces
hwali
hyperfocus1338
igormukhingmailcom
imjoseangel
infigoKriti
ipergenitsa
iredmail
ivandigiusto
jadbaz
jaikdean
jamescassell
janosmiko
jarnold-timeout
JaSafieddine
jborean93
jctanner
jean-christophe-manciot
Jean-Daniel
jgornick
jhagg
jhoekx
jirib
jkleckner
jkordish
jlaska
Jmainguy
jochu
JoelFeiner
johnavp1989
jonatasbaldin
Jorge-Rodriguez
jpjaatin
jpmens
JSafieddine
jsmartin
juergenhoetzel
jw34
kalaisubbiah
kenichi-ogawa-1988
kkeane
klingac
kotso
kuntalFreshBooks
kurtdavis
larsks
ldesgrange
leeadh
LeonB
leucos
loomsen
lorin
lowwalker
lperezs
makmanalp
manuelmorena
MarcinOrlowski
markdorison
markotitel
marktheunissen
markuman
mattclay
matt-horwood-mayden
mavimo
maxamillion
maxbube
mcgoldrickm
meanstrong
meersjo
megamisan
michaeldg
michalmedvecky
MikeiLL
milky-milk
milosz
mistaka0s
mklassen
mkrizek
mmoya
mohag
mohsenSy
mpdehaan
MRwangyd
mverwijs
mvgrimes
mysqlbox
netmonk
nhojpatrick
nicolas-g
NielsH
nitinkansal1984
nitzmahone
Ompragash
on
order
organman91
p53
pakal
paulbadcock
pennycoders
petoju
petracvv
pgrenaud
philfry
pileofrogs
pkaramol
platypus-geek
plumbeo
pratikgadiya12
pshanbhag
r0bj
rajsshah86
reduzent
relrod
resmo
ricco24
richlv
riupie
rndmh3ro
robertdebock
robpblake
rokka-n
Roxyrob
roysmith
rthouvenin
ruudk
samccann
samdoran
sayap
scottbrown
seanorama
sedrubal
sergey-trukhin
Shaps
shrikeh
sivel
skalfyfan
skoriy88
sperantus
spoyd
steverweber
steveteahan
stijnopheide
stintel
stoned
strixBE
SWADESNA
tapologo
tejatsk14
tersmitten
the
the02
thomasliddledba
time-palominodb
timorunge
Tomasthanes
tomdymond
Tronde
tvlooy
tyll
UncertaintyP
unnecessary-username
vamshi8
vanne
vdboor
vmahadev
v-zhuravlev
webmat
wedi
whysthatso
willthames
windowsansiblernew
wrosario
xiata
Xyon
yangchao0512
ziegenberg
Zverik

5
MAINTAINERS Normal file
View file

@ -0,0 +1,5 @@
bmalynovytch
Jorge-Rodriguez
rsicart
laurent-indermuehle
Andersson007 (andersson007_ in #ansible-community IRC/Matrix)

3
MAINTAINING.md Normal file
View file

@ -0,0 +1,3 @@
# Maintaining this collection
Refer to the [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst).

48
PSF-license.txt Normal file
View file

@ -0,0 +1,48 @@
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.

View file

@ -1,5 +1,52 @@
# MySQL collection for Ansible
[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql)
[![Plugins CI](https://github.com/ansible-collections/community.mysql/workflows/Plugins%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Plugins+CI") [![Roles CI](https://github.com/ansible-collections/community.mysql/workflows/Roles%20CI/badge.svg?event=push)](https://github.com/ansible-collections/community.mysql/actions?query=workflow%3A"Roles+CI") [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.mysql)](https://codecov.io/gh/ansible-collections/community.mysql) [![Discuss on Matrix at #mysql:ansible.com](https://img.shields.io/matrix/mysql:ansible.com.svg?server_fqdn=ansible-accounts.ems.host&label=Discuss%20on%20Matrix%20at%20%23mysql:ansible.com&logo=matrix)](https://matrix.to/#/#mysql:ansible.com)
This collection is a part of the Ansible package.
## Code of Conduct
We follow the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our interactions within this project.
If you encounter abusive behavior violating the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html), please refer to the [policy violations](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html#policy-violations) section of the Code of Conduct for information on how to raise a complaint.
## Contributing
The content of this collection is made by [people](https://github.com/ansible-collections/community.mysql/blob/main/CONTRIBUTORS) just like you, a community of individuals collaborating on making the world better through developing automation software.
We are actively accepting new contributors.
Any kind of contribution is very welcome.
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.mysql/blob/main/CONTRIBUTING.md)!
## Collection maintenance
The current maintainers (contributors with `write` or higher access) are listed in the [MAINTAINERS](https://github.com/ansible-collections/community.mysql/blob/main/MAINTAINERS) file. If you have questions or need help, feel free to mention them in the proposals.
To learn how to maintain / become a maintainer of this collection, refer to the [Maintainer guidelines](https://github.com/ansible-collections/community.mysql/blob/main/MAINTAINING.md).
It is necessary for maintainers of this collection to be subscribed to:
* The collection itself (the `Watch` button -> `All Activity` in the upper right corner of the repository's homepage).
* The "Changes Impacting Collection Contributors and Maintainers" [issue](https://github.com/ansible-collections/overview/issues/45).
They also should be subscribed to Ansible's [The Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn).
## Communication
We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). Be sure you are subscribed.
Join us on Matrix in the `#mysql:ansible.com` [room](https://matrix.to/#/#mysql:ansible.com), the `#users:ansible.com` [room](https://matrix.to/#/#users:ansible.com) (general use questions and support), `#ansible-community:ansible.com` [room](https://matrix.to/#/#community:ansible.com) (community and collection development questions), and other Matrix rooms or corresponding bridged Libera.Chat channels. See the [Ansible Communication Guide](https://docs.ansible.com/ansible/devel/community/communication.html) for details.
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
For more information about communication, refer to the [Ansible Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
## Governance
The process of decision making in this collection is based on discussing and finding consensus among participants.
Every voice is important and every idea is valuable. If you have something on your mind, create an issue or dedicated discussion and let's discuss it!
## Included content
@ -11,16 +58,31 @@
- [mysql_user](https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_user_module.html)
- [mysql_variables](https://docs.ansible.com/ansible/latest/collections/community/mysql/mysql_variables_module.html)
## Tested with Ansible
## Tested with
### ansible-core
- 2.9
- 2.10
- 2.11
- devel
- 2.12
- 2.13
- current development version
### Databases
- mysql 5.7.31
- mysql 8.0.22
- mariadb 10.3.34 (only collection version >= 3)
- mariadb 10.8.3 (only collection version >= 3)
### Database connectors
- pymysql 0.7.10
- pymysql 0.9.3
- mysqlclient 2.0.1
## External requirements
The MySQL modules rely on a MySQL connector. The list of supported drivers is below:
The MySQL modules rely on a MySQL connector. The list of supported drivers is below:
- [PyMySQL](https://github.com/PyMySQL/PyMySQL)
- [MySQLdb](https://github.com/PyMySQL/mysqlclient-python)
@ -44,12 +106,20 @@ collections:
- name: community.mysql
```
Note that if you install the collection from Ansible Galaxy, it will not be upgraded automatically if you upgrade the Ansible package. To upgrade the collection to the latest available version, run the following command:
```bash
ansible-galaxy collection install community.mysql --upgrade
```
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax:
```bash
ansible-galaxy collection install community.mysql:==2.0.0
```
See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
## Contributing
See the [contribution guide](CONTRIBUTING.md).
## Licensing
<!-- Include the appropriate license information here and a pointer to the full licensing details. If the collection contains modules migrated from the ansible/ansible repo, you must use the same license that existed in the ansible/ansible repo. See the GNU license example below. -->

View file

@ -1,38 +0,0 @@
# Review Checklist
When reviewing, keep in mind that we follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our contributions and interactions within this repository.
If you are a committer, also refer to the [Ansible committer guidelines](https://docs.ansible.com/ansible/devel/community/committer_guidelines.html).
**General tips**
- Try to create a culture of collaboration when reviewing
- Welcome the author and thank them for the pull request
- When suggesting changes, try to use questions, not statements
- When suggesting mandatory changes, do it as politely as possible providing documentation references
- If your suggestion is optional or a matter of personal preferences, please say it explicitly
- When asking for adding tests or for complex code refactoring, say that the author is welcome to ask for clarifications and help if they need
- If somebody suggests a good idea, mention it or put a thumbs up
- After merging, thank the author and reviewers for their time and effort
**Standards and documentation**
- [ ] if the pull request is not a documentation fix, it must include a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#creating-a-changelog-fragment) - please check the format carefully
- [ ] if new files are added with the pull request, they follow the [licensing rules](https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#licensing)
- [ ] the changes follow the [Ansible documentation standards](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html) and the [style guide](https://docs.ansible.com/ansible/devel/dev_guide/style_guide/index.html#style-guide)
- [ ] the changes follow the [development conventions](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html)
- [ ] if a new plugin is added, it is one of the [allowed plugin types](https://github.com/ansible-collections/overview/blob/main/collection_requirements.rst#modules-plugins)
- [ ] documentation, examples, and return sections use FQCNs for the `M(..)` [format macros](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#linking-and-other-format-macros-within-module-documentation) when referring to modules
- [ ] modules and plugins from ansible-core use `ansible.builtin.` as a FQCN prefix when mentioned
- [ ] when a new option, module, plugin, or return value is added, the corresponding documentation or return sections use `version_added:` containing the *collection* version which they will be first released in
* this usually is the next minor release, sometimes the next major release (example: if 2.7.5 is the current release, the next minor release will be 2.8.0, and the next major release will be 3.0.0)
- [ ] FQCNs are used for `extends_documentation_fragment:`, unless the author is referring to doc_fragments from ansible-core
**Tests (if applicable and technically possible to implement)**
- [ ] the pull request has [integration tests](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html)
- [ ] the pull request has [unit tests](https://docs.ansible.com/ansible/devel/dev_guide/testing_units.html)
- [ ] all changes are covered
- [ ] integration tests also cover `check_mode` (if it is supported)
- [ ] integration tests check an actual state of the system, not only what the module reports (for example, if the module changes a file, check that the file was actually changed by using the `ansible.builtin.stat` module)
**Other**
- [ ] the pull request does not contain merge commits (see GitHub warnings at the bottom of the pull request) - in this case, ask the author to rebase the pull request branch
- [ ] if the pull request contains breaking changes, ask the author and the collection maintainers if it is really needed and there is no way not to introduce them

View file

@ -235,3 +235,178 @@ releases:
- 107-mysql_user_fix_grant_on_col_handling.yml
- 97-mysql_replication_deprecate_offending_terminology.yml
release_date: '2021-03-08'
1.4.0:
changes:
bugfixes:
- mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105).
major_changes:
- mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires``
option in ``community.mysql`` 2.0.0 and support will be dropped altogether
in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121).
minor_changes:
- mysql module utils - change deprecated connection parameters ``passwd`` and
``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116).
- mysql_collection - introduce codebabse split to handle divergences between
MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103).
- mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114).
- mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101).
release_summary: 'This is the minor release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection
that have been added after the release of ``community.mysql`` 1.3.0.'''
fragments:
- 1.4.0.yml
- 101-drop-requiressl-support.yml
- 103-mysql_and_mariadb_divergence.yml
- 108-mysql_priv_add_grant.yml
- 115-add_mysql_full_version_suffix_return_var.yml
- 116-change_deprecated_connection_ parameters.yml
release_date: '2021-04-16'
1.4.1:
changes:
bugfixes:
- mysql - revert changes of connector arguments made in pull request 116 causing
the invalid keyword argument error (https://github.com/ansible-collections/community.mysql/pull/116).
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection
that have been added after the release of ``community.mysql`` 1.4.0.'
fragments:
- 1.4.1.yml
- 153-mysql_revert_connector_changes.yml
release_date: '2021-04-23'
1.4.2:
changes:
minor_changes:
- mysql_query - correctly reflect changed status in replace statements (https://github.com/ansible-collections/community.mysql/pull/193).
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.1.'
fragments:
- 1.4.2.yml
- 193-reflect_changed_status_in_replace_statements.yml
release_date: '2021-08-11'
1.4.3:
changes:
bugfixes:
- mysql_info - fix TypeError failure when there are databases that do not contain
tables (https://github.com/ansible-collections/community.mysql/issues/204).
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.2.'
fragments:
- 1.4.3.yml
- 205-mysql_info_fix_failure_when_no_tables_in_db.yml
release_date: '2021-09-23'
1.4.4:
changes:
bugfixes:
- Collection core functions - use vendored version of ``distutils.version``
instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/community.mysql/pull/269).
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.3.'
fragments:
- 1.4.4.yml
- 267-prepare_for_distutils_be_removed.yml
release_date: '2022-01-18'
1.4.5:
changes:
bugfixes:
- mysql_user - fix missing dynamic privileges after revoke and grant privileges
to user (https://github.com/ansible-collections/community.mysql/issues/120).
- mysql_user - fix parsing privs when a user has roles assigned (https://github.com/ansible-collections/community.mysql/issues/231).
- 'mysql_user - fix the possibility for a race condition that breaks certain
(circular) replication configurations when ``DROP USER`` is executed on multiple
nodes in the replica set. Adding ``IF EXISTS`` avoids the need to use ``sql_log_bin:
no`` making the statement always replication safe (https://github.com/ansible-collections/community.mysql/pull/287).'
major_changes:
- The community.mysql collection no longer supports ``Ansible 2.9`` and ``ansible-base
2.10``. While we take no active measures to prevent usage and there are no
plans to introduce incompatible code to the modules, we will stop testing
against ``Ansible 2.9`` and ``ansible-base 2.10``. Both will very soon be
End of Life and if you are still using them, you should consider upgrading
to the ``latest Ansible / ansible-core 2.11 or later`` as soon as possible
(https://github.com/ansible-collections/community.mysql/pull/343).
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.4.'
fragments:
- 001-mysql_user_fix_pars_users_with_roles_assigned.yml
- 1.4.5.yml
- 307-mysql_user_add_if_exists_to_drop.yml
- 338-mysql_user_fix.yml
- drop_support_of_2.9-2.10.yml
release_date: '2022-05-13'
1.4.6:
changes:
bugfixes:
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.5.'
fragments:
- 1.4.6.yml
- psf-license.yml
release_date: '2022-05-17'
1.4.7:
changes:
bugfixes:
- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause
is used (https://github.com/ansible-collections/community.mysql/issues/268).
- mysql_user - fix logic when ``update_password`` is set to ``on_create`` for
users using ``plugin*`` arguments (https://github.com/ansible-collections/community.mysql/issues/334).
The ``on_create`` sets ``password`` to None for old mysql_native_authentication
but not for authentiation methods which uses the ``plugin*`` arguments. This
PR changes this so ``on_create`` also exchange ``plugin``, ``plugin_hash_string``,
``plugin_auth_string`` to None in the list of arguments to change
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.6.'
fragments:
- 1.4.7.yml
- 322-mysql_query_fix_false_change_report.yml
- 334-mysql_user_fix_logic_on_oncreate.yml
release_date: '2022-06-02'
1.4.8:
changes:
bugfixes:
- Include ``simplified_bsd.txt`` license file for various module utils.
release_summary: 'This is the patch release of the ``community.mysql`` collection.
This changelog contains all changes to the modules in this collection that
have been added after the release of ``community.mysql`` 1.4.7.'
fragments:
- 1.4.8.yml
- simplified-bsd-license.yml
release_date: '2022-07-28'
1.5.0:
changes:
minor_changes:
- mysql_info - add ``connector_name`` and ``connector_version`` to returned
values (https://github.com/ansible-collections/community.mysql/pull/497).
release_summary: 'This is bugfix release of the ``community.mysql`` collection.
This changelog contains all changes to the modules and plugins in this collection
that have been made after the previous release.'
fragments:
- 1.5.0.yml
- 497_mysql_info_returns_connector_name_and_version.yml
- backport-stable-2-pr-452.yml
release_date: '2023-02-08'

View file

@ -1,4 +1,4 @@
changelog_filename_template: CHANGELOG.rst
changelog_filename_template: ../CHANGELOG.rst
changelog_filename_version_depth: 0
changes_file: changelog.yaml
changes_format: combined

View file

@ -1,4 +0,0 @@
minor_changes:
- mysql_user - deprecate the ``REQUIRESSL`` privilege (https://github.com/ansible-collections/community.mysql/issues/101).
major_changes:
- mysql_user - the ``REQUIRESSL`` is an alias for the ``ssl`` key in the ``tls_requires`` option in ``community.mysql`` 2.0.0 and support will be dropped altogether in ``community.mysql`` 3.0.0 (https://github.com/ansible-collections/community.mysql/issues/121).

View file

@ -1,2 +0,0 @@
minor_changes:
- mysql_collection - introduce codebabse split to handle divergences between MySQL and MariaDB (https://github.com/ansible-collections/community.mysql/pull/103).

View file

@ -1,2 +0,0 @@
bugfixes:
- mysql_user - add support for ``REPLICA MONITOR`` privilege (https://github.com/ansible-collections/community.mysql/issues/105).

View file

@ -1,2 +0,0 @@
minor_changes:
- mysql_info - add `version.full` and `version.suffix` return values (https://github.com/ansible-collections/community.mysql/issues/114).

View file

@ -1,2 +0,0 @@
minor_changes:
- mysql module utils - change deprecated connection parameters ``passwd`` and ``db`` to ``password`` and ``database`` (https://github.com/ansible-collections/community.mysql/pull/116).

View file

@ -1,6 +1,6 @@
namespace: community
name: mysql
version: 1.3.0
version: 1.5.0
readme: README.md
authors:
- Ansible community

View file

@ -35,6 +35,7 @@ options:
login_unix_socket:
description:
- The path to a Unix domain socket for local connections.
- Use this parameter to avoid the C(Please explicitly state intended protocol) error.
type: str
connect_timeout:
description:
@ -44,6 +45,9 @@ options:
config_file:
description:
- Specify a config file from which user and password are to be read.
- The default config file, C(~/.my.cnf), if it exists, will be read, even if I(config_file) is not specified.
- The default config file, C(~/.my.cnf), if it exists, must contain a C([client]) section as a MySQL connector requirement.
- To prevent the default config file from being read, set I(config_file) to be an empty string.
type: path
default: '~/.my.cnf'
ca_cert:
@ -67,21 +71,25 @@ options:
- Whether to validate the server host name when an SSL connection is required. Corresponds to MySQL CLIs C(--ssl) switch.
- Setting this to C(false) disables hostname verification. Use with caution.
- Requires pymysql >= 0.7.11.
- This optoin has no effect on MySQLdb.
- This option has no effect on MySQLdb.
type: bool
version_added: '1.1.0'
requirements:
- PyMySQL (Python 2.7 and Python 3.X), or
- mysqlclient (Python 3.5+) or
- PyMySQL (Python 2.7 and Python 3.x) or
- MySQLdb (Python 2.x)
notes:
- Requires the PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) package installed on the remote host.
The Python package may be installed with apt-get install python-pymysql (Ubuntu; see M(ansible.builtin.apt)) or
yum install python2-PyMySQL (RHEL/CentOS/Fedora; see M(ansible.builtin.yum)). You can also use dnf install python2-PyMySQL
for newer versions of Fedora; see M(ansible.builtin.dnf).
- Be sure you have PyMySQL or MySQLdb library installed on the target machine
for the Python interpreter Ansible uses, for example, if it is Python 3,
you must install the library for Python 3. You can also change the interpreter.
For more information, see U(https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html).
- Be sure you have mysqlclient, PyMySQL, or MySQLdb library installed on the target machine
for the Python interpreter Ansible discovers. For example if ansible discovers and uses Python 3, you need to install
the Python 3 version of PyMySQL or mysqlclient. If ansible discovers and uses Python 2, you need to install the Python 2
version of either PyMySQL or MySQL-python.
- If you have trouble, it may help to force Ansible to use the Python interpreter you need by specifying
C(ansible_python_interpreter). For more information, see
U(https://docs.ansible.com/ansible/latest/reference_appendices/interpreter_discovery.html).
- Both C(login_password) and C(login_user) are required when you are
passing credentials. If none are present, the module will attempt to read
the credentials from C(~/.my.cnf), and finally fall back to using the MySQL
@ -94,4 +102,12 @@ notes:
- Alternatively, you can use the mysqlclient library instead of MySQL-python (MySQLdb)
which supports both Python 2.X and Python >=3.5.
See U(https://pypi.org/project/mysqlclient/) how to install it.
- "If credentials from the config file (for example, C(/root/.my.cnf)) are not needed to connect to a database server, but
the file exists and does not contain a C([client]) section, before any other valid directives, it will be read and this
will cause the connection to fail, to prevent this set it to an empty string, (for example C(config_file: ''))."
- "To avoid the C(Please explicitly state intended protocol) error, use the I(login_unix_socket) argument,
for example, C(login_unix_socket: /run/mysqld/mysqld.sock)."
- Alternatively, to avoid using I(login_unix_socket) argument on each invocation you can specify the socket path
using the `socket` option in your MySQL config file (usually C(~/.my.cnf)) on the destination host, for
example C(socket=/var/lib/mysql/mysql.sock).
'''

View file

@ -0,0 +1,343 @@
# Vendored copy of distutils/version.py from CPython 3.9.5
#
# Implements multiple version numbering conventions for the
# Python Module Distribution Utilities.
#
# PSF License (see PSF-license.txt or https://opensource.org/licenses/Python-2.0)
#
"""Provides classes to represent module version numbers (one class for
each style of version numbering). There are currently two such classes
implemented: StrictVersion and LooseVersion.
Every version number class implements the following interface:
* the 'parse' method takes a string and parses it to some internal
representation; if the string is an invalid version number,
'parse' raises a ValueError exception
* the class constructor takes an optional string argument which,
if supplied, is passed to 'parse'
* __str__ reconstructs the string that was passed to 'parse' (or
an equivalent string -- ie. one that will generate an equivalent
version number instance)
* __repr__ generates Python code to recreate the version number instance
* _cmp compares the current instance with either another instance
of the same class or a string (which will be parsed to an instance
of the same class, thus must follow the same rules)
"""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import re
try:
RE_FLAGS = re.VERBOSE | re.ASCII
except AttributeError:
RE_FLAGS = re.VERBOSE
class Version:
"""Abstract base class for version numbering classes. Just provides
constructor (__init__) and reproducer (__repr__), because those
seem to be the same for all version numbering classes; and route
rich comparisons to _cmp.
"""
def __init__(self, vstring=None):
if vstring:
self.parse(vstring)
def __repr__(self):
return "%s ('%s')" % (self.__class__.__name__, str(self))
def __eq__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c == 0
def __lt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c < 0
def __le__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c <= 0
def __gt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c > 0
def __ge__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c >= 0
# Interface for version-number classes -- must be implemented
# by the following classes (the concrete ones -- Version should
# be treated as an abstract class).
# __init__ (string) - create and take same action as 'parse'
# (string parameter is optional)
# parse (string) - convert a string representation to whatever
# internal representation is appropriate for
# this style of version numbering
# __str__ (self) - convert back to a string; should be very similar
# (if not identical to) the string supplied to parse
# __repr__ (self) - generate Python code to recreate
# the instance
# _cmp (self, other) - compare two version numbers ('other' may
# be an unparsed version string, or another
# instance of your version class)
class StrictVersion(Version):
"""Version numbering for anal retentives and software idealists.
Implements the standard interface for version number classes as
described above. A version number consists of two or three
dot-separated numeric components, with an optional "pre-release" tag
on the end. The pre-release tag consists of the letter 'a' or 'b'
followed by a number. If the numeric components of two version
numbers are equal, then one with a pre-release tag will always
be deemed earlier (lesser) than one without.
The following are valid version numbers (shown in the order that
would be obtained by sorting according to the supplied cmp function):
0.4 0.4.0 (these two are equivalent)
0.4.1
0.5a1
0.5b3
0.5
0.9.6
1.0
1.0.4a3
1.0.4b1
1.0.4
The following are examples of invalid version numbers:
1
2.7.2.2
1.3.a4
1.3pl1
1.3c4
The rationale for this version numbering system will be explained
in the distutils documentation.
"""
version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',
RE_FLAGS)
def parse(self, vstring):
match = self.version_re.match(vstring)
if not match:
raise ValueError("invalid version number '%s'" % vstring)
(major, minor, patch, prerelease, prerelease_num) = \
match.group(1, 2, 4, 5, 6)
if patch:
self.version = tuple(map(int, [major, minor, patch]))
else:
self.version = tuple(map(int, [major, minor])) + (0,)
if prerelease:
self.prerelease = (prerelease[0], int(prerelease_num))
else:
self.prerelease = None
def __str__(self):
if self.version[2] == 0:
vstring = '.'.join(map(str, self.version[0:2]))
else:
vstring = '.'.join(map(str, self.version))
if self.prerelease:
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
return vstring
def _cmp(self, other):
if isinstance(other, str):
other = StrictVersion(other)
elif not isinstance(other, StrictVersion):
return NotImplemented
if self.version != other.version:
# numeric versions don't match
# prerelease stuff doesn't matter
if self.version < other.version:
return -1
else:
return 1
# have to compare prerelease
# case 1: neither has prerelease; they're equal
# case 2: self has prerelease, other doesn't; other is greater
# case 3: self doesn't have prerelease, other does: self is greater
# case 4: both have prerelease: must compare them!
if (not self.prerelease and not other.prerelease):
return 0
elif (self.prerelease and not other.prerelease):
return -1
elif (not self.prerelease and other.prerelease):
return 1
elif (self.prerelease and other.prerelease):
if self.prerelease == other.prerelease:
return 0
elif self.prerelease < other.prerelease:
return -1
else:
return 1
else:
raise AssertionError("never get here")
# end class StrictVersion
# The rules according to Greg Stein:
# 1) a version number has 1 or more numbers separated by a period or by
# sequences of letters. If only periods, then these are compared
# left-to-right to determine an ordering.
# 2) sequences of letters are part of the tuple for comparison and are
# compared lexicographically
# 3) recognize the numeric components may have leading zeroes
#
# The LooseVersion class below implements these rules: a version number
# string is split up into a tuple of integer and string components, and
# comparison is a simple tuple comparison. This means that version
# numbers behave in a predictable and obvious way, but a way that might
# not necessarily be how people *want* version numbers to behave. There
# wouldn't be a problem if people could stick to purely numeric version
# numbers: just split on period and compare the numbers as tuples.
# However, people insist on putting letters into their version numbers;
# the most common purpose seems to be:
# - indicating a "pre-release" version
# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
# - indicating a post-release patch ('p', 'pl', 'patch')
# but of course this can't cover all version number schemes, and there's
# no way to know what a programmer means without asking him.
#
# The problem is what to do with letters (and other non-numeric
# characters) in a version number. The current implementation does the
# obvious and predictable thing: keep them as strings and compare
# lexically within a tuple comparison. This has the desired effect if
# an appended letter sequence implies something "post-release":
# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
#
# However, if letters in a version number imply a pre-release version,
# the "obvious" thing isn't correct. Eg. you would expect that
# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
# implemented here, this just isn't so.
#
# Two possible solutions come to mind. The first is to tie the
# comparison algorithm to a particular set of semantic rules, as has
# been done in the StrictVersion class above. This works great as long
# as everyone can go along with bondage and discipline. Hopefully a
# (large) subset of Python module programmers will agree that the
# particular flavour of bondage and discipline provided by StrictVersion
# provides enough benefit to be worth using, and will submit their
# version numbering scheme to its domination. The free-thinking
# anarchists in the lot will never give in, though, and something needs
# to be done to accommodate them.
#
# Perhaps a "moderately strict" version class could be implemented that
# lets almost anything slide (syntactically), and makes some heuristic
# assumptions about non-digits in version number strings. This could
# sink into special-case-hell, though; if I was as talented and
# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
# just as happy dealing with things like "2g6" and "1.13++". I don't
# think I'm smart enough to do it right though.
#
# In any case, I've coded the test suite for this module (see
# ../test/test_version.py) specifically to fail on things like comparing
# "1.2a2" and "1.2". That's not because the *code* is doing anything
# wrong, it's because the simple, obvious design doesn't match my
# complicated, hairy expectations for real-world version numbers. It
# would be a snap to fix the test suite to say, "Yep, LooseVersion does
# the Right Thing" (ie. the code matches the conception). But I'd rather
# have a conception that matches common notions about version numbers.
class LooseVersion(Version):
"""Version numbering for anarchists and software realists.
Implements the standard interface for version number classes as
described above. A version number consists of a series of numbers,
separated by either periods or strings of letters. When comparing
version numbers, the numeric components will be compared
numerically, and the alphabetic components lexically. The following
are all valid version numbers, in no particular order:
1.5.1
1.5.2b2
161
3.10a
8.02
3.4j
1996.07.12
3.2.pl0
3.1.1.6
2g6
11g
0.960923
2.2beta29
1.13++
5.5.kw
2.0b1pl0
In fact, there is no such thing as an invalid version number under
this scheme; the rules for comparison are simple and predictable,
but may not always give the results you want (for some definition
of "want").
"""
component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
def __init__(self, vstring=None):
if vstring:
self.parse(vstring)
def parse(self, vstring):
# I've given up on thinking I can reconstruct the version string
# from the parsed tuple -- so I just store the string here for
# use by __str__
self.vstring = vstring
components = [x for x in self.component_re.split(vstring) if x and x != '.']
for i, obj in enumerate(components):
try:
components[i] = int(obj)
except ValueError:
pass
self.version = components
def __str__(self):
return self.vstring
def __repr__(self):
return "LooseVersion ('%s')" % str(self)
def _cmp(self, other):
if isinstance(other, str):
other = LooseVersion(other)
elif not isinstance(other, LooseVersion):
return NotImplemented
if self.version == other.version:
return 0
if self.version < other.version:
return -1
if self.version > other.version:
return 1
# end class LooseVersion

View file

@ -6,7 +6,7 @@
#
# Copyright (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
#
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

View file

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version
from distutils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion
def uses_replica_terminology(cursor):

View file

@ -1,7 +1,11 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from distutils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version

View file

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version
from distutils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion
def uses_replica_terminology(cursor):

View file

@ -1,7 +1,11 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from distutils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.mysql import get_server_version

View file

@ -7,7 +7,7 @@
# Copyright (c), Jonathan Mainguy <jon@soh.re>, 2015
# Most of this was originally added by Sven Schliesing @muffl0n in the mysql_user.py module
#
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Simplified BSD License (see simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import (absolute_import, division, print_function)
from functools import reduce
@ -23,13 +23,54 @@ try:
_mysql_cursor_param = 'cursor'
except ImportError:
try:
# mysqlclient is called MySQLdb
import MySQLdb as mysql_driver
import MySQLdb.cursors
_mysql_cursor_param = 'cursorclass'
except ImportError:
mysql_driver = None
mysql_driver_fail_msg = 'The PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) module is required.'
mysql_driver_fail_msg = ('A MySQL module is required: for Python 2.7 either PyMySQL, or '
'MySQL-python, or for Python 3.X mysqlclient or PyMySQL. '
'Consider setting ansible_python_interpreter to use '
'the intended Python version.')
def get_connector_name(connector):
""" (class) -> str
Return the name of the connector (pymysql or mysqlclient (MySQLdb))
or 'Unknown' if not pymysql or MySQLdb. When adding a
connector here, also modify get_connector_version.
"""
if connector is None or not hasattr(connector, '__name__'):
return 'Unknown'
return connector.__name__
def get_connector_version(connector):
""" (class) -> str
Return the version of pymysql or mysqlclient (MySQLdb).
Return 'Unknown' if the connector name is unknown.
"""
if connector is None:
return 'Unknown'
connector_name = get_connector_name(connector)
if connector_name == 'pymysql':
# pymysql has two methods:
# - __version__ that returns the string: 0.7.11.None
# - VERSION that returns the tuple (0, 7, 11, None)
v = connector.VERSION[:3]
return '.'.join(map(str, v))
elif connector_name == 'MySQLdb':
# version_info returns the tuple (2, 1, 1, 'final', 0)
v = connector.version_info[:3]
return '.'.join(map(str, v))
else:
return 'Unknown'
def parse_from_mysql_config_file(cnf):
@ -79,7 +120,7 @@ def mysql_connect(module, login_user=None, login_password=None, config_file='',
if login_user is not None:
config['user'] = login_user
if login_password is not None:
config['password'] = login_password
config['passwd'] = login_password
if ssl_cert is not None:
config['ssl']['cert'] = ssl_cert
if ssl_key is not None:
@ -87,7 +128,7 @@ def mysql_connect(module, login_user=None, login_password=None, config_file='',
if ssl_ca is not None:
config['ssl']['ca'] = ssl_ca
if db is not None:
config['database'] = db
config['db'] = db
if connect_timeout is not None:
config['connect_timeout'] = connect_timeout
if check_hostname is not None:

View file

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Provide version object to compare version numbers."""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
# Once we drop support for ansible-core 2.11, we can
# remove the _version.py file, and replace the following import by
#
# from ansible.module_utils.compat.version import LooseVersion
from ._version import LooseVersion

View file

@ -53,12 +53,12 @@ options:
description:
- Execute the dump in a single transaction.
type: bool
default: no
default: false
quick:
description:
- Option used for dumping large tables.
type: bool
default: yes
default: true
ignore_tables:
description:
- A list of table names that will be ignored in the dump
@ -70,14 +70,14 @@ options:
description:
- Dump binary columns using hexadecimal notation.
type: bool
default: no
default: false
version_added: '0.1.0'
force:
description:
- Continue dump or import even if we get an SQL error.
- Used only when I(state) is C(dump) or C(import).
type: bool
default: no
default: false
version_added: '0.1.0'
master_data:
description:
@ -96,7 +96,7 @@ options:
description:
- Skip locking tables for read. Used when I(state=dump), ignored otherwise.
type: bool
default: no
default: false
version_added: '0.1.0'
dump_extra_args:
description:
@ -110,7 +110,7 @@ options:
- If C(yes), the module will internally execute commands via a shell.
- Used when I(state=import), ignored otherwise.
type: bool
default: no
default: false
version_added: '0.1.0'
unsafe_login_password:
description:
@ -121,7 +121,7 @@ options:
- Used only when I(state) is C(import) or C(dump) and
I(login_password) is passed, ignored otherwise.
type: bool
default: no
default: false
version_added: '0.1.0'
restrict_config_file:
description:
@ -132,14 +132,14 @@ options:
under the hood that read named option file in addition to usual option files.
- If this behavior is undesirable, use C(yes) to read only named option file.
type: bool
default: no
default: false
version_added: '0.1.0'
check_implicit_admin:
description:
- Check if mysql allows login as root/nopassword before trying supplied credentials.
- If success, passed I(login_user)/I(login_password) will be ignored.
type: bool
default: no
default: false
version_added: '0.1.0'
config_overrides_defaults:
description:
@ -148,7 +148,7 @@ options:
- Used when I(stat) is C(present) or C(absent), ignored otherwise.
- It needs Python 3.5+ as the default interpreter on a target host.
type: bool
default: no
default: false
version_added: '0.1.0'
seealso:
@ -183,10 +183,13 @@ extends_documentation_fragment:
'''
EXAMPLES = r'''
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Create a new database with name 'bobdata'
community.mysql.mysql_db:
name: bobdata
state: present
login_unix_socket: /run/mysqld/mysqld.sock
- name: Create new databases with names 'foo' and 'bar'
community.mysql.mysql_db:
@ -212,7 +215,7 @@ EXAMPLES = r'''
name: my_db
state: import
target: /tmp/dump.sql.bz2
force: yes
force: true
- name: Dump multiple databases
community.mysql.mysql_db:
@ -284,7 +287,7 @@ EXAMPLES = r'''
- name: Try to create database as root/nopassword first. If not allowed, pass the credentials
community.mysql.mysql_db:
check_implicit_admin: yes
check_implicit_admin: true
login_user: bob
login_password: 123456
name: bobdata
@ -442,7 +445,7 @@ def db_import(module, host, user, password, db_name, target, all_databases, port
cmd.append("--defaults-extra-file=%s" % shlex_quote(config_file))
if check_implicit_admin:
cmd += " --user=root --password=''"
cmd.append("--user=root --password=''")
else:
if user:
cmd.append("--user=%s" % shlex_quote(user))

View file

@ -42,7 +42,7 @@ options:
description:
- Includes names of empty databases to returned dictionary.
type: bool
default: no
default: false
notes:
- Calculating the size of a database might be slow, depending on the number and size of tables in it.
@ -58,6 +58,7 @@ seealso:
author:
- Andrew Klychkov (@Andersson007)
- Sebastian Gumprich (@rndmh3ro)
- Laurent Indermühle (@laurent-indermuehle)
extends_documentation_fragment:
- community.mysql.mysql
@ -76,9 +77,12 @@ EXAMPLES = r'''
# Display all info from databases group except settings:
# ansible databases -m mysql_info -a 'filter=!settings'
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Collect all possible information using passwordless root access
community.mysql.mysql_info:
login_user: root
login_unix_socket: /run/mysqld/mysqld.sock
- name: Get MySQL version with non-default credentials
community.mysql.mysql_info:
@ -93,14 +97,14 @@ EXAMPLES = r'''
filter: "!settings,!users"
- name: Collect info about databases and version using ~/.my.cnf as a credential file
become: yes
become: true
community.mysql.mysql_info:
filter:
- databases
- version
- name: Collect info about databases and version using ~alice/.my.cnf as a credential file
become: yes
become: true
community.mysql.mysql_info:
config_file: /home/alice/.my.cnf
filter:
@ -108,13 +112,13 @@ EXAMPLES = r'''
- version
- name: Collect info about databases including empty and excluding their sizes
become: yes
become: true
community.mysql.mysql_info:
config_file: /home/alice/.my.cnf
filter:
- databases
exclude_fields: db_size
return_empty_dbs: yes
return_empty_dbs: true
'''
RETURN = r'''
@ -203,6 +207,21 @@ slave_hosts:
type: dict
sample:
- { "2": { "Host": "", "Master_id": 1, "Port": 3306 } }
connector_name:
description: Name of the python connector used by the module. When the connector is not identified, returns C(Unknown).
returned: always
type: str
sample:
- "pymysql"
- "MySQLdb"
version_added: '1.5.0'
connector_version:
description: Version of the python connector used by the module. When the connector is not identified, returns C(Unknown).
returned: always
type: str
sample:
- "1.0.2"
version_added: '1.5.0'
'''
from decimal import Decimal
@ -213,6 +232,8 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import (
mysql_common_argument_spec,
mysql_driver,
mysql_driver_fail_msg,
get_connector_name,
get_connector_version,
)
from ansible.module_utils.six import iteritems
from ansible.module_utils._text import to_native
@ -474,6 +495,9 @@ class MySQL_Info(object):
self.info['databases'][db['name']] = {}
if not exclude_fields or 'db_size' not in exclude_fields:
if db['size'] is None:
db['size'] = 0
self.info['databases'][db['name']]['size'] = int(db['size'])
# If empty dbs are not needed in the returned dict, exit from the method
@ -552,21 +576,29 @@ def main():
if mysql_driver is None:
module.fail_json(msg=mysql_driver_fail_msg)
connector_name = get_connector_name(mysql_driver)
connector_version = get_connector_version(mysql_driver)
try:
cursor, db_conn = mysql_connect(module, login_user, login_password,
config_file, ssl_cert, ssl_key, ssl_ca, db,
check_hostname=check_hostname,
connect_timeout=connect_timeout, cursor_class='DictCursor')
except Exception as e:
module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. "
"Exception message: %s" % (config_file, to_native(e)))
msg = ('unable to connect to database using %s %s, check login_user '
'and login_password are correct or %s has the credentials. '
'Exception message: %s' % (connector_name, connector_version, config_file, to_native(e)))
module.fail_json(msg)
###############################
# Create object and do main job
mysql = MySQL_Info(module, cursor)
module.exit_json(changed=False, **mysql.get_info(filter_, exclude_fields, return_empty_dbs))
module.exit_json(changed=False,
connector_name=connector_name,
connector_version=connector_version,
**mysql.get_info(filter_, exclude_fields, return_empty_dbs))
if __name__ == '__main__':

View file

@ -22,8 +22,12 @@ options:
description:
- SQL query to run. Multiple queries can be passed using YAML list syntax.
- Must be a string or YAML list containing strings.
- Note that if you use the C(IF EXISTS/IF NOT EXISTS) clauses in your query
and C(mysqlclient) connector, the module will report that
the state has been changed even if it has not. If it is important in your
workflow, use the C(PyMySQL) connector instead.
type: raw
required: yes
required: true
positional_args:
description:
- List of values to be passed as positional arguments to the query.
@ -42,7 +46,7 @@ options:
description:
- Where passed queries run in a single transaction (C(yes)) or commit them one-by-one (C(no)).
type: bool
default: no
default: false
seealso:
- module: community.mysql.mysql_db
author:
@ -53,10 +57,13 @@ extends_documentation_fragment:
'''
EXAMPLES = r'''
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Simple select query to acme db
community.mysql.mysql_query:
login_db: acme
query: SELECT * FROM orders
login_unix_socket: /run/mysqld/mysqld.sock
- name: Select query to db acme with positional arguments
community.mysql.mysql_query:
@ -80,7 +87,7 @@ EXAMPLES = r'''
query:
- INSERT INTO articles (id, story) VALUES (2, 'my_long_story')
- INSERT INTO prices (id, price) VALUES (123, '100.00')
single_transaction: yes
single_transaction: true
'''
RETURN = r'''
@ -103,6 +110,8 @@ rowcount:
sample: [5, 1]
'''
import warnings
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.mysql.plugins.module_utils.mysql import (
mysql_connect,
@ -112,7 +121,7 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import (
)
from ansible.module_utils._text import to_native
DML_QUERY_KEYWORDS = ('INSERT', 'UPDATE', 'DELETE')
DML_QUERY_KEYWORDS = ('INSERT', 'UPDATE', 'DELETE', 'REPLACE')
# TRUNCATE is not DDL query but it also returns 0 rows affected:
DDL_QUERY_KEYWORDS = ('CREATE', 'DROP', 'ALTER', 'RENAME', 'TRUNCATE')
@ -196,9 +205,22 @@ def main():
executed_queries = []
rowcount = []
already_exists = False
for q in query:
try:
cursor.execute(q, arguments)
with warnings.catch_warnings():
warnings.filterwarnings(action='error',
message='.*already exists*',
category=mysql_driver.Warning)
try:
cursor.execute(q, arguments)
except mysql_driver.Warning:
# When something is run with IF NOT EXISTS
# and there's "already exists" MySQL warning,
# set the flag as True.
# PyMySQL throws the warning, mysqlclinet does NOT.
already_exists = True
except Exception as e:
if not autocommit:
@ -208,7 +230,8 @@ def main():
module.fail_json(msg="Cannot execute SQL '%s' args [%s]: %s" % (q, arguments, to_native(e)))
try:
query_result.append([dict(row) for row in cursor.fetchall()])
if not already_exists:
query_result.append([dict(row) for row in cursor.fetchall()])
except Exception as e:
if not autocommit:
@ -224,8 +247,12 @@ def main():
for keyword in DDL_QUERY_KEYWORDS:
if keyword in q:
changed = True
if already_exists:
# Indicates the entity already exists
changed = False
already_exists = False # Reset flag
else:
changed = True
try:
executed_queries.append(cursor._last_executed)
except AttributeError:

View file

@ -167,7 +167,7 @@ options:
description:
- Fails on error when calling mysql.
type: bool
default: False
default: false
version_added: '0.1.0'
notes:
@ -191,9 +191,12 @@ seealso:
'''
EXAMPLES = r'''
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Stop mysql replica thread
community.mysql.mysql_replication:
mode: stopreplica
login_unix_socket: /run/mysqld/mysqld.sock
- name: Get master binlog file name and binlog position
community.mysql.mysql_replication:
@ -243,12 +246,12 @@ EXAMPLES = r'''
community.mysql.mysql_replication:
mode: startreplica
connection_name: master-1
fail_on_error: yes
fail_on_error: true
- name: Change master and fail on error (like when replica thread is running)
community.mysql.mysql_replication:
mode: changemaster
fail_on_error: yes
fail_on_error: true
'''
@ -272,7 +275,7 @@ from ansible_collections.community.mysql.plugins.module_utils.mysql import (
mysql_common_argument_spec,
)
from ansible.module_utils._text import to_native
from distutils.version import LooseVersion
from ansible_collections.community.mysql.plugins.module_utils.version import LooseVersion
executed_queries = []

View file

@ -22,13 +22,14 @@ options:
required: true
password:
description:
- Set the user's password.
- Set the user's password. Only for C(mysql_native_password) authentication.
For other authentication plugins see the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string).
type: str
encrypted:
description:
- Indicate that the 'password' field is a `mysql_native_password` hash.
type: bool
default: no
default: false
host:
description:
- The 'host' part of the MySQL username.
@ -40,12 +41,12 @@ options:
to all hostnames for a given user.
- This option cannot be used when creating users.
type: bool
default: no
default: false
priv:
description:
- "MySQL privileges string in the format: C(db.table:priv1,priv2)."
- "Multiple privileges can be specified by separating each one using
a forward slash: C(db.table:priv/db.table:priv)."
a forward slash: C(db.table1:priv/db.table2:priv)."
- The format is based on MySQL C(GRANT) statement.
- Database and table names can be quoted, MySQL-style.
- If column privileges are used, the C(priv1,priv2) part must be
@ -53,13 +54,19 @@ options:
the module will always report changes. It includes grouping columns
by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))).
- Can be passed as a dictionary (see the examples).
- Supports GRANTs for procedures and functions (see the examples).
- "Note: If you pass the same C(db.table) combination to this parameter
two or more times with different privileges,
for example, C('*.*:SELECT/*.*:SHOW VIEW'), only the last one will be applied,
in this example, it will be C(SHOW VIEW) respectively.
Use C('*.*:SELECT,SHOW VIEW') instead to apply both."
type: raw
append_privs:
description:
- Append the privileges defined by priv to the existing ones for this
user instead of overwriting existing ones.
type: bool
default: no
default: false
tls_requires:
description:
- Set requirement for secure transport as a dictionary of requirements (see the examples).
@ -72,7 +79,7 @@ options:
description:
- Whether binary logging should be enabled or disabled for the connection.
type: bool
default: yes
default: true
state:
description:
- Whether the user should exist.
@ -85,11 +92,11 @@ options:
- Check if mysql allows login as root/nopassword before trying supplied credentials.
- If success, passed I(login_user)/I(login_password) will be ignored.
type: bool
default: no
default: false
update_password:
description:
- C(always) will update passwords if they differ.
- C(on_create) will only set the password for newly created users.
- C(always) will update passwords if they differ. This affects I(password) and the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string).
- C(on_create) will only set the password or the combination of plugin, plugin_hash_string, plugin_auth_string for newly created users.
type: str
choices: [ always, on_create ]
default: always
@ -145,16 +152,19 @@ extends_documentation_fragment:
'''
EXAMPLES = r'''
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Removes anonymous user account for localhost
community.mysql.mysql_user:
name: ''
host: localhost
state: absent
login_unix_socket: /run/mysqld/mysqld.sock
- name: Removes all anonymous user accounts
community.mysql.mysql_user:
name: ''
host_all: yes
host_all: true
state: absent
- name: Create database user with name 'bob' and password '12345' with all database privileges
@ -168,7 +178,7 @@ EXAMPLES = r'''
community.mysql.mysql_user:
name: bob
password: '*EE0D72C1085C46C5278932678FBE2C6A782821B4'
encrypted: yes
encrypted: true
priv: '*.*:ALL'
state: present
@ -188,6 +198,15 @@ EXAMPLES = r'''
'db1.*': 'ALL,GRANT'
'db2.*': 'ALL,GRANT'
# Use 'PROCEDURE' instead of 'FUNCTION' to apply GRANTs for a MySQL procedure instead.
- name: Grant a user the right to execute a function
community.mysql.mysql_user:
name: readonly
password: 12345
priv:
FUNCTION my_db.my_function: EXECUTE
state: present
# Note that REQUIRESSL is a special privilege that should only apply to *.* by itself.
# Setting this privilege in this manner is deprecated.
# Use 'tls_requires' instead.
@ -230,7 +249,7 @@ EXAMPLES = r'''
If mysql allows root/nopassword login, try it without the credentials first.
If it's not allowed, pass the credentials
community.mysql.mysql_user:
check_implicit_admin: yes
check_implicit_admin: true
login_user: root
login_password: 123456
name: sally
@ -239,7 +258,7 @@ EXAMPLES = r'''
- name: Ensure no user named 'sally' exists at all
community.mysql.mysql_user:
name: sally
host_all: yes
host_all: true
state: absent
- name: Specify grants composed of more than one word
@ -271,7 +290,7 @@ EXAMPLES = r'''
password: 12345
priv: "*.*:USAGE"
state: present
sql_log_bin: no
sql_log_bin: false
- name: Create user 'bob' authenticated with plugin 'AWSAuthenticationPlugin'
community.mysql.mysql_user:
@ -379,7 +398,7 @@ def sanitize_requires(tls_requires):
if tls_requires:
for key in tls_requires.keys():
sanitized_requires[key.upper()] = tls_requires[key]
if any([key in ["CIPHER", "ISSUER", "SUBJECT"] for key in sanitized_requires.keys()]):
if any(key in ["CIPHER", "ISSUER", "SUBJECT"] for key in sanitized_requires.keys()):
sanitized_requires.pop("SSL", None)
sanitized_requires.pop("X509", None)
return sanitized_requires
@ -694,7 +713,10 @@ def user_delete(cursor, user, host, host_all, check_mode):
hostnames = [host]
for hostname in hostnames:
cursor.execute("DROP USER %s@%s", (user, hostname))
try:
cursor.execute("DROP USER IF EXISTS %s@%s", (user, hostname))
except Exception:
cursor.execute("DROP USER %s@%s", (user, hostname))
return True
@ -732,8 +754,19 @@ def privileges_get(cursor, user, host):
for grant in grants:
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0])
if res is None:
# If a user has roles assigned, we'll have one of priv tuples looking like
# GRANT `admin`@`%` TO `user1`@`localhost`
# which will result None as res value.
# As we use the mysql_role module (community.mysql 2.0.0+) to manipulate roles
# we just ignore such privs below:
res = re.match("""GRANT (.+) TO (['`"]).*""", grant[0])
if res:
continue
raise InvalidPrivsError('unable to parse the MySQL grant string: %s' % grant[0])
privileges = res.group(1).split(",")
privileges = [pick(x.strip()) for x in privileges]
@ -934,6 +967,7 @@ def privileges_revoke(cursor, user, host, db_table, priv, grant_option):
query.append("FROM %s@%s")
query = ' '.join(query)
cursor.execute(query, (user, host))
cursor.execute("FLUSH PRIVILEGES")
def privileges_grant(cursor, user, host, db_table, priv, tls_requires):
@ -1233,7 +1267,7 @@ def main():
priv, append_privs, tls_requires, module)
else:
changed, msg = user_mod(cursor, user, host, host_all, None, encrypted,
plugin, plugin_hash_string, plugin_auth_string,
None, None, None,
priv, append_privs, tls_requires, module)
except (SQLParseError, InvalidPrivsError, mysql_driver.Error) as e:

View file

@ -22,7 +22,7 @@ options:
description:
- Variable name to operate.
type: str
required: yes
required: true
value:
description:
- If set, then sets variable value to this.
@ -58,9 +58,12 @@ extends_documentation_fragment:
'''
EXAMPLES = r'''
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Check for sync_binlog setting
community.mysql.mysql_variables:
variable: sync_binlog
login_unix_socket: /run/mysqld/mysqld.sock
- name: Set read_only variable to 1 persistently
community.mysql.mysql_variables:

8
simplified_bsd.txt Normal file
View file

@ -0,0 +1,8 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,13 +1,18 @@
dbdeployer_version: 1.52.0
dbdeployer_version: 1.64.0
dbdeployer_home_dir: /opt/dbdeployer
home_dir: /root
percona_client_version: 5.7
mariadb_install: false
mysql_version: 8.0.22
mariadb_version: 10.5.4
mysql_base_port: 3306
percona_client_package: >-
{%- if mariadb_install -%}
mariadb-client
{%- else -%}
percona-server-client-5.7
{%- endif -%}

View file

@ -6,10 +6,10 @@
- name: "{{ role_name }} | config | run unpack tarball"
shell:
cmd: "dbdeployer unpack {{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }}"
cmd: "dbdeployer unpack {{ dbdeployer_sandbox_download_dir }}/{{ install_tarball }} --flavor {{ install_type }}"
creates: "{{ dbdeployer_sandbox_binary_dir }}/{{ install_version }}"
- name: "{{ role_name }} | config | setup replication topology"
shell:
cmd: "dbdeployer deploy multiple {{ install_version }} --base-port {{ mysql_base_port }} --my-cnf-options=\"master_info_repository='TABLE'\" --my-cnf-options=\"relay_log_info_repository='TABLE'\""
cmd: "dbdeployer deploy multiple {{ install_version }} --flavor {{ install_type }} --base-port {{ mysql_base_port }} --my-cnf-options=\"master_info_repository='TABLE'\" --my-cnf-options=\"relay_log_info_repository='TABLE'\""
creates: "{{ dbdeployer_sandbox_home_dir }}/multi_msb_{{ install_version|replace('.','_') }}"

View file

@ -4,12 +4,26 @@
keyserver: keyserver.ubuntu.com
id: 4D1BB29D63D98E422B2113B19334A25F8507EFA5
state: present
when: install_type == 'mysql'
- name: "{{ role_name }} | install | add percona repositories"
apt_repository:
repo: "{{ item }}"
repo: deb http://repo.percona.com/percona/apt {{ ansible_lsb.codename }} main
state: present
loop: "{{ percona_mysql_repos }}"
when: install_type == 'mysql'
- name: "{{ role_name }} | install | add apt signing key for mariadb"
apt_key:
keyserver: keyserver.ubuntu.com
id: F1656F24C74CD1D8
state: present
when: install_type == 'mariadb'
- name: "{{ role_name }} | install | add mariadb repositories"
apt_repository:
repo: "deb [arch=amd64,arm64] https://downloads.mariadb.com/MariaDB/mariadb-{{ mysql_major_version }}/repo/ubuntu {{ ansible_lsb.codename }} main"
state: present
when: install_type == 'mariadb'
- name: "{{ role_name }} | install | install packages required by percona"
apt:
@ -28,6 +42,23 @@
- name: "{{ role_name }} | install | install python packages"
pip:
name: "{{ python_packages }}"
register: connector
- name: Extract connector.name.0 content
set_fact:
connector_name: "{{ connector.name.0 }}"
- name: Debug connector_name content
debug:
msg: '{{ connector_name }}'
- name: Extract connector version
set_fact:
connector_ver: "{{ connector_name.split('=')[2].strip() }}"
- name: Debug connector_ver var content
debug:
msg: '{{ connector_ver }}'
- name: "{{ role_name }} | install | install packages required by mysql"
apt:

View file

@ -1,7 +1,12 @@
---
- name: "{{ role_name }} | setvars | split mysql version in parts"
set_fact:
mysql_version_parts: "{{ mysql_version.split('.') }}"
mysql_version_parts: >-
{%- if mariadb_install -%}
{{ mariadb_version.split('.') }}
{%- else -%}
{{ mysql_version.split('.') }}
{%- endif -%}
- name: "{{ role_name }} | setvars | get mysql major version"
set_fact:

View file

@ -7,25 +7,24 @@ dbdeployer_sandbox_download_dir: "{{ home_dir }}/downloads"
dbdeployer_sandbox_binary_dir: "{{ home_dir }}/opt/mysql"
dbdeployer_sandbox_home_dir: "{{ home_dir }}/sandboxes"
percona_mysql_repos:
- deb http://repo.percona.com/apt {{ ansible_lsb.codename }} main
- deb-src http://repo.percona.com/apt {{ ansible_lsb.codename }} main
percona_mysql_packages:
- percona-server-client-{{ percona_client_version }}
- "{{ percona_client_package }}"
python_packages: [pymysql == 0.9.3]
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://dev.mysql.com/get/Downloads/MySQL-{{ mysql_major_version }}/{{ mysql_tarball }}"
mariadb_tarball: "mariadb-{{ mariadb_version }}-linux-x86_64.tar.gz"
mariadb_src: "https://downloads.mariadb.com/MariaDB/mariadb-{{ mariadb_version }}/bintar-linux-x86_64/{{ mariadb_tarball }}"
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

@ -4,7 +4,18 @@ mysql_user: root
mysql_password: msandbox
mysql_primary_port: 3307
db_name: 'data'
# Database names
db_names:
- "data"
# - "db%"
# Don't test % in stable-1. Support was added in v2
# Database formats
db_formats:
- { format_type: "sql", file: "dbdata.sql", format_msg_type: "ASCII", file2: "dump2.sql", file3: "dump3.sql", file4: "dump4.sql" }
- { format_type: "gz", file: "dbdata.gz", format_msg_type: "gzip", file2: "dump2.gz", file3: "dump3.gz", file4: "dump4.gz" }
- { format_type: "bz2", file: "dbdata.bz2", format_msg_type: "bzip2", file2: "dump2.bz2", file3: "dump3.bz2", file4: "dump4.bz2" }
db_name2: 'data2'
db_user1: 'datauser1'
db_user2: 'datauser2'

View file

@ -11,27 +11,41 @@
- name: Add fake port to config file
shell: 'echo "port = {{ fake_port }}" >> {{ config_file }}'
- name: Get pymysql version
shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: Add blank line
shell: 'echo "" >> {{ config_file }}'
when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=')
when:
- >
connector_name is not search('pymysql')
or (
connector_name is search('pymysql')
and connector_ver is version('0.9.3', '>=')
)
- name: Create include_dir
file:
path: '{{ include_dir }}'
state: directory
mode: '0777'
when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=')
when:
- >
connector_name is not search('pymysql')
or (
connector_name is search('pymysql')
and connector_ver is version('0.9.3', '>=')
)
- name: Add include_dir
lineinfile:
path: '{{ config_file }}'
line: '!includedir {{ include_dir }}'
insertafter: EOF
when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '>=')
when:
- >
connector_name is not search('pymysql')
or (
connector_name is search('pymysql')
and connector_ver is version('0.9.3', '>=')
)
- name: Create database using fake port to connect to, must fail
mysql_db:

View file

@ -45,7 +45,7 @@
encoding: latin1
target: "{{ latin1_file1 }}"
state: dump
register: dump_result
register: result
- assert:
that:
@ -78,6 +78,7 @@
encoding: latin1
name: '{{ db_latin1_name }}'
target: "{{ latin1_file1 }}"
register: result
- assert:
that:

View file

@ -1,16 +1,20 @@
---
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -49,12 +53,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_db:

View file

@ -21,306 +21,45 @@
# 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: remove database if it exists
command: >
"{{ mysql_command }} -sse 'drop database {{ db_name }}'"
ignore_errors: True
- name: Check state present/absent
include_tasks: state_present_absent.yml
vars:
db_name: "{{ item }}"
loop: "{{ db_names }}"
- name: make sure the test database is not there
command: "{{ mysql_command }} {{ db_name }}"
register: mysql_db_check
failed_when: "'1049' not in mysql_db_check.stderr"
- name: Check state dump/import
include_tasks: state_dump_import.yml
vars:
db_name: "{{ item.0 }}"
file: "{{ item.1.file }}"
file2: "{{ item.1.file2 }}"
file3: "{{ item.1.file3 }}"
file4: "{{ item.1.file4 }}"
format_msg_type: "{{ item.1.format_msg_type }}"
format_type: "{{ item.1.format_type }}"
with_nested:
- "{{ db_names }}"
- "{{ db_formats }}"
- name: test state=present for a database name (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_name }}'
state: present
register: result
- name: Check state present/absent with multiple databases
include_tasks: multi_db_create_delete.yml
- name: assert output message that database exist
assert:
that:
- result is changed
- result.db == '{{ db_name }}'
- result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"]
- name: Check state dump/import with encoding
include_tasks: encoding_dump_import.yml
vars:
file: "latin1.sql"
format_msg_type: "ASCII"
- name: run command to test state=present for a database name (expect db_name in stdout)
command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\""
register: result
- name: assert database exist
assert:
that:
- "'{{ db_name }}' in result.stdout"
# ============================================================
- name: test state=absent for a database name (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_name }}'
state: absent
register: result
- name: assert output message that database does not exist
assert:
that:
- result is changed
- result.db == '{{ db_name }}'
- result.executed_commands == ["DROP DATABASE `{{ db_name }}`"]
- name: run command to test state=absent for a database name (expect db_name not in stdout)
command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_name }}' not in result.stdout"
# ============================================================
- name: test mysql_db encoding param not valid - issue 8075
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: datanotvalid
state: present
encoding: notvalid
register: result
ignore_errors: true
- name: assert test mysql_db encoding param not valid - issue 8075 (failed=true)
assert:
that:
- "result.failed == true"
- "'Traceback' not in result.msg"
- "'Unknown character set' in result.msg"
# ============================================================
- name: test mysql_db using a valid encoding utf8 (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: present
encoding: utf8
register: result
- name: assert output message created a database
assert:
that:
- result is changed
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"]
- name: test database was created
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE en{{ db_name }}\""
register: result
- name: assert created database is of encoding utf8
assert:
that:
- "'utf8' in result.stdout"
- name: remove database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: absent
# ============================================================
- name: test mysql_db using valid encoding binary (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: present
encoding: binary
register: result
- name: assert output message that database was created
assert:
that:
- result is changed
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"]
- name: run command to test database was created
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE en{{ db_name }}\""
register: result
- name: assert created database is of encoding binary
assert:
that:
- "'binary' in result.stdout"
- name: remove database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: absent
# ============================================================
- name: create user1 to access database dbuser1
mysql_user:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: user1
password: 'Hfd6fds^dfA8Ga'
priv: '*.*:ALL'
state: present
- name: create database dbuser1 using user1
mysql_db:
login_user: user1
login_password: 'Hfd6fds^dfA8Ga'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: present
register: result
- name: assert output message that database was created
assert:
that:
- "result.changed == true"
- name: run command to test database was created using user1
command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 }}'\""
register: result
- name: assert database exist
assert:
that:
- "'{{ db_user1 }}' in result.stdout"
# ============================================================
- name: create user2 to access database with privilege select only
mysql_user:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: user2
password: 'kjsfd&F7safjad'
priv: '*.*:SELECT'
state: present
- name: create database dbuser2 using user2 with no privilege to create (expect failed=true)
mysql_db:
login_user: user2
login_password: 'kjsfd&F7safjad'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user2 }}'
state: present
register: result
ignore_errors: true
- name: assert output message that database was not created using dbuser2
assert:
that:
- "result.failed == true"
- "'Access denied' in result.msg"
- name: run command to test that database was not created
command: "{{ mysql_command }} -e \"show databases like '{{ db_user2 }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_user2 }}' not in result.stdout"
# ============================================================
- name: delete database using user2 with no privilege to delete (expect failed=true)
mysql_db:
login_user: user2
login_password: 'kjsfd&F7safjad'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: absent
register: result
ignore_errors: true
- name: assert output message that database was not deleted using dbuser2
assert:
that:
- "result.failed == true"
- "'Access denied' in result.msg"
- name: run command to test database was not deleted
command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 }}'\""
register: result
- name: assert database still exist
assert:
that:
- "'{{ db_user1 }}' in result.stdout"
# ============================================================
- name: delete database using user1 with all privilege to delete a database (expect changed=true)
mysql_db:
login_user: user1
login_password: 'Hfd6fds^dfA8Ga'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: absent
register: result
ignore_errors: true
- name: assert output message that database was deleted using user1
assert:
that:
- result is changed
- result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"]
- name: run command to test database was deleted using user1
command: "{{ mysql_command }} -e \"show databases like '{{ db_name }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_user1 }}' not in result.stdout"
# ============================================================
- include: state_dump_import.yml format_type=sql file=dbdata.sql format_msg_type=ASCII file2=dump2.sql file3=dump3.sql file4=dump4.sql
- include: state_dump_import.yml format_type=gz file=dbdata.gz format_msg_type=gzip file2=dump2.gz file3=dump3.gz file4=dump4.gz
- include: state_dump_import.yml format_type=bz2 file=dbdata.bz2 format_msg_type=bzip2 file2=dump2.bz2 file3=dump3.bz2 file4=dump4.bz2
- include: multi_db_create_delete.yml
- include: encoding_dump_import.yml file=latin1.sql format_msg_type=ASCII
- include: config_overrides_defaults.yml
- name: Check MySQL config file
include_tasks: config_overrides_defaults.yml
when: ansible_python.version_info[0] >= 3
- include: issue-28.yml
- name: Check issue 28
include_tasks: issue-28.yml
vars:
db_name: "{{ item }}"
loop: "{{ db_names }}"

View file

@ -14,6 +14,18 @@
#
# ==========================================================================
# Initial check - To confirm that database does not exist before executing check mode tasks
- name: Drop databases before test
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name:
- '{{ db1_name }}'
- '{{ db2_name }}'
- '{{ db3_name }}'
state: absent
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
register: mysql_result
@ -44,7 +56,7 @@
- name: assert successful completion of create database using check_mode since databases does not exist prior
assert:
that:
- check_mode_result.changed == true
- check_mode_result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -75,7 +87,7 @@
- name: assert successful completion of create database
assert:
that:
- result.changed == true
- result is changed
- result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}']
- name: run command to list databases like specified database name
@ -108,7 +120,7 @@
- name: assert that recreation of existing databases does not make change (since recreated using check mode)
assert:
that:
- check_mode_result.changed == false
- check_mode_result is not changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -139,7 +151,7 @@
- name: assert that recreation of existing databases does not make change
assert:
that:
- result.changed == false
- result is not changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -168,7 +180,7 @@
- name: assert successful completion of deleting database
assert:
that:
- result.changed == true
- result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -200,7 +212,7 @@
- name: assert successful completion of recreation of partially existing database using check mode
assert:
that:
- check_mode_result.changed == true
- check_mode_result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -231,7 +243,7 @@
- name: assert successful completion of create database
assert:
that:
- result.changed == true
- result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -272,7 +284,7 @@
- name: assert successful completion of dump operation using check mode
assert:
that:
- check_mode_dump_result.changed == true
- check_mode_dump_result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -389,7 +401,7 @@
- name: assert successful completion of dump operation
assert:
that:
- dump_result.changed == true
- dump_result is changed
- dump_result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}']
- name: run command to list databases like specified database name
@ -439,7 +451,7 @@
- name: assert successful completion of dump operation
assert:
that:
- dump_result.changed == true
- dump_result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -479,7 +491,7 @@
- name: assert successful completion of delete databases which already exists using check mode
assert:
that:
- check_mode_result.changed == true
- check_mode_result is changed
- name: run command to test state=absent for a database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -508,7 +520,7 @@
- name: assert successful completion of deleting database
assert:
that:
- result.changed == true
- result is changed
- result.db_list == ['{{ db2_name }}', '{{ db3_name }}']
- name: run command to list databases like specified database name
@ -539,7 +551,7 @@
- name: assert that deletion of non existing databases does not make change (using check mode)
assert:
that:
- check_mode_result.changed == false
- check_mode_result is not changed
- name: run command to test state=absent for a database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -568,7 +580,7 @@
- name: assert that deletion of non existing databases does not make change
assert:
that:
- result.changed == false
- result is not changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
@ -600,7 +612,7 @@
- name: assert successful completion of deleting database
assert:
that:
- result.changed == true
- result is changed
- name: run command to list databases like specified database name
command: "{{ mysql_command }} \"-e show databases like 'database%'\""

View file

@ -159,7 +159,7 @@
- name: assert successful completion of dump operation (with multiple databases in list form) via check mode
assert:
that:
- "dump_result.changed == true"
- dump_result is changed
- name: database dump file2 should not exist
stat:
@ -187,7 +187,7 @@
- name: assert successful completion of dump operation (with multiple databases in list form)
assert:
that:
- "dump_result2.changed == true"
- dump_result2 is changed
- name: state dump - dump file2 should exist
file:
@ -249,7 +249,7 @@
- name: assert output message restored a database from dump file1
assert:
that:
- "import_result.changed == true"
- import_result is changed
- name: remove database
mysql_db:
@ -284,7 +284,7 @@
- name: assert output message restored a database from dump file2 (check mode)
assert:
that:
- "check_import_result.changed == true"
- check_import_result is changed
- name: run command to list databases
command: "{{ mysql_command }} \"-e show databases like 'data%'\""
@ -309,7 +309,7 @@
- name: assert output message restored a database from dump file2
assert:
that:
- import_result2.changed == true
- import_result2 is changed
- import_result2.db_list == ['{{ db_name2 }}']
- name: run command to list databases
@ -335,7 +335,7 @@
- name: assert output message backup the database
assert:
that:
- "result.changed == true"
- result is changed
- "result.db =='{{ db_name }}'"
# - name: assert database was backed up successfully
@ -364,7 +364,7 @@
- name: assert output message restore the database
assert:
that:
- "result.changed == true"
- result is changed
- name: select data from table employee
command: "{{ mysql_command }} {{ db_name }} \"-e select * from employee\""
@ -398,7 +398,7 @@
- assert:
that:
- result.failed == true
- result is failed
- name: try to import with force parameter
mysql_db:

View file

@ -0,0 +1,300 @@
# test code for mysql_db module with database name containing special chars
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# ============================================================
- name: remove database if it exists
command: >
"{{ mysql_command }} -sse 'DROP DATABASE IF EXISTS {{ db_name }}'"
ignore_errors: true
- name: make sure the test database is not there
command: "{{ mysql_command }} {{ db_name }}"
register: mysql_db_check
failed_when: "'1049' not in mysql_db_check.stderr"
- name: test state=present for a database name (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_name }}'
state: present
register: result
- name: assert output message that database exist
assert:
that:
- result is changed
- result.db == '{{ db_name }}'
- result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"]
- name: run command to test state=present for a database name (expect db_name in stdout)
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database exist
assert:
that:
- "'{{ db_name }}' in result.stdout"
# ============================================================
- name: test state=absent for a database name (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_name }}'
state: absent
register: result
- name: assert output message that database does not exist
assert:
that:
- result is changed
- result.db == '{{ db_name }}'
- result.executed_commands == ["DROP DATABASE `{{ db_name }}`"]
- name: run command to test state=absent for a database name (expect db_name not in stdout)
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_name }}' not in result.stdout"
# ============================================================
- name: test mysql_db encoding param not valid - issue 8075
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: datanotvalid
state: present
encoding: notvalid
register: result
ignore_errors: true
- name: assert test mysql_db encoding param not valid - issue 8075 (failed=true)
assert:
that:
- result is failed
- "'Traceback' not in result.msg"
- "'Unknown character set' in result.msg"
# ============================================================
- name: test mysql_db using a valid encoding utf8 (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: present
encoding: utf8
register: result
- name: assert output message created a database
assert:
that:
- result is changed
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"]
- name: test database was created
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
register: result
- name: assert created database is of encoding utf8
assert:
that:
- "'utf8' in result.stdout"
- name: remove database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: absent
# ============================================================
- name: test mysql_db using valid encoding binary (expect changed=true)
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: present
encoding: binary
register: result
- name: assert output message that database was created
assert:
that:
- result is changed
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"]
- name: run command to test database was created
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
register: result
- name: assert created database is of encoding binary
assert:
that:
- "'binary' in result.stdout"
- name: remove database
mysql_db:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: 'en{{ db_name }}'
state: absent
# ============================================================
- name: create user1 to access database dbuser1
mysql_user:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: user1
password: 'Hfd6fds^dfA8Ga'
priv: '*.*:ALL'
state: present
- name: create database dbuser1 using user1
mysql_db:
login_user: user1
login_password: 'Hfd6fds^dfA8Ga'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: present
register: result
- name: assert output message that database was created
assert:
that:
- result is changed
- name: run command to test database was created using user1
command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database exist
assert:
that:
- "'{{ db_user1 }}' in result.stdout"
# ============================================================
- name: create user2 to access database with privilege select only
mysql_user:
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: user2
password: 'kjsfd&F7safjad'
priv: '*.*:SELECT'
state: present
- name: create database dbuser2 using user2 with no privilege to create (expect failed=true)
mysql_db:
login_user: user2
login_password: 'kjsfd&F7safjad'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user2 }}'
state: present
register: result
ignore_errors: true
- name: assert output message that database was not created using dbuser2
assert:
that:
- result is failed
- "'Access denied' in result.msg"
- name: run command to test that database was not created
command: "{{ mysql_command }} -e \"show databases like '{{ db_user2 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_user2 }}' not in result.stdout"
# ============================================================
- name: delete database using user2 with no privilege to delete (expect failed=true)
mysql_db:
login_user: user2
login_password: 'kjsfd&F7safjad'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: absent
register: result
ignore_errors: true
- name: assert output message that database was not deleted using dbuser2
assert:
that:
- result is failed
- "'Access denied' in result.msg"
- name: run command to test database was not deleted
command: "{{ mysql_command }} -e \"show databases like '{{ db_user1 | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database still exist
assert:
that:
- "'{{ db_user1 }}' in result.stdout"
# ============================================================
- name: delete database using user1 with all privilege to delete a database (expect changed=true)
mysql_db:
login_user: user1
login_password: 'Hfd6fds^dfA8Ga'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
name: '{{ db_user1 }}'
state: absent
register: result
ignore_errors: true
- name: assert output message that database was deleted using user1
assert:
that:
- result is changed
- result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"]
- name: run command to test database was deleted using user1
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
register: result
- name: assert database does not exist
assert:
that:
- "'{{ db_user1 }}' not in result.stdout"

View file

@ -0,0 +1,32 @@
---
# Added in 1.5.0, 2.4.0 and 3.6.0 in
# https://github.com/ansible-collections/community.mysql/pull/497
# TODO: Refactor in PR490.
- name: Connector info | Assert connector_name exists and has expected values
ansible.builtin.assert:
that:
- result.connector_name is defined
- result.connector_name is in ['pymysql', 'MySQLdb']
success_msg: >-
Assertions passed, result.connector_name is {{ result.connector_name }}
fail_msg: >-
Assertion failed, result.connector_name is
{{ result.connector_name | d('Unknown')}} which is different than expected
pymysql or MySQLdb
# TODO: Refactor in PR490.
- name: Connector info | Assert connector_version exists and has expected values
ansible.builtin.assert:
that:
- result.connector_version is defined
- >
result.connector_version == 'Unknown'
or result.connector_version is version(connector_ver, '==')
success_msg: >-
Assertions passed, result.connector_version is
{{ result.connector_version }}
fail_msg: >-
Assertion failed, result.connector_version is
{{ result.connector_version }} which is different than expected
{{ connector_ver }}

View file

@ -1,16 +1,24 @@
---
- name: alias mysql command to include default options
set_fact:
mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp"
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -47,12 +55,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_info:

View file

@ -47,14 +47,18 @@
- assert:
that:
- result.changed == false
- "mysql_version in result.version.full"
- result is not changed
- "mysql_version in result.version.full or mariadb_version in result.version.full"
- result.settings != {}
- result.global_status != {}
- result.databases != {}
- result.engines != {}
- result.users != {}
- name: mysql_info - Test connector informations display
ansible.builtin.import_tasks:
file: connector_info.yml
# Access by non-default cred file
- name: mysql_info - check non-default cred file
mysql_info:
@ -66,7 +70,7 @@
- assert:
that:
- result.changed == false
- result is not changed
- result.version != {}
# Remove cred files
@ -86,8 +90,8 @@
- assert:
that:
- result.changed == false
- result.version != {}
- result is not changed
- result.version != {}
# Test excluding
- name: Collect all info except settings and users
@ -98,13 +102,13 @@
- assert:
that:
- result.changed == false
- result.version != {}
- result.global_status != {}
- result.databases != {}
- result.engines != {}
- result.settings is not defined
- result.users is not defined
- result is not changed
- result.version != {}
- result.global_status != {}
- result.databases != {}
- result.engines != {}
- result.settings is not defined
- result.users is not defined
# Test including
- name: Collect info only about version and databases
@ -117,13 +121,13 @@
- assert:
that:
- result.changed == false
- result.version != {}
- result.databases != {}
- result.engines is not defined
- result.settings is not defined
- result.global_status is not defined
- result.users is not defined
- result is not changed
- result.version != {}
- result.databases != {}
- result.engines is not defined
- result.settings is not defined
- result.global_status is not defined
- result.users is not defined
# Test exclude_fields: db_size
# 'unsupported' element is passed to check that an unsupported value
@ -140,9 +144,9 @@
- assert:
that:
- result.changed == false
- result.databases != {}
- result.databases.mysql == {}
- result is not changed
- result.databases != {}
- result.databases.mysql == {}
########################################################
# Issue #65727, empty databases must be in returned dict
@ -163,9 +167,9 @@
# Check acme is in returned dict
- assert:
that:
- result.changed == false
- result.databases.acme.size == 0
- result.databases.mysql != {}
- result is not changed
- result.databases.acme.size == 0
- result.databases.mysql != {}
- name: Collect info about databases excluding their sizes
mysql_info:
@ -180,9 +184,9 @@
# Check acme is in returned dict
- assert:
that:
- result.changed == false
- result.databases.acme == {}
- result.databases.mysql == {}
- result is not changed
- result.databases.acme == {}
- result.databases.mysql == {}
- name: Remove acme database
mysql_db:
@ -191,3 +195,25 @@
state: absent
- include: issue-28.yml
# https://github.com/ansible-collections/community.mysql/issues/204
- name: Create database containing only views
mysql_db:
<<: *mysql_params
name: allviews
- name: Create view
mysql_query:
<<: *mysql_params
login_db: allviews
query: 'CREATE VIEW v_today (today) AS SELECT CURRENT_DATE'
- name: Fetch info
mysql_info:
<<: *mysql_params
register: result
- name: Check
assert:
that:
- result.databases.allviews.size == 0

View file

@ -7,6 +7,7 @@ test_db: testdb
test_table1: test1
test_table2: test2
test_table3: test3
test_table4: test4
test_script_path: /tmp/test.sql
user_name_1: 'db_user1'

View file

@ -1,16 +1,24 @@
---
- name: alias mysql command to include default options
set_fact:
mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp"
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -47,12 +55,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_query:

View file

@ -18,8 +18,8 @@
- assert:
that:
- result is changed
- result.executed_queries == ['CREATE DATABASE {{ test_db }}']
- result is changed
- result.executed_queries == ['CREATE DATABASE {{ test_db }}']
- name: Create {{ test_table1 }}
mysql_query:
@ -30,8 +30,8 @@
- assert:
that:
- result is changed
- result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)']
- result is changed
- result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)']
- name: Insert test data
mysql_query:
@ -45,9 +45,9 @@
- assert:
that:
- result is changed
- result.rowcount == [2, 1]
- result.executed_queries == ['INSERT INTO {{ test_table1 }} VALUES (1), (2)', 'INSERT INTO {{ test_table1 }} VALUES (3)']
- result is changed
- result.rowcount == [2, 1]
- result.executed_queries == ['INSERT INTO {{ test_table1 }} VALUES (1), (2)', 'INSERT INTO {{ test_table1 }} VALUES (3)']
- name: Check data in {{ test_table1 }}
mysql_query:
@ -58,12 +58,12 @@
- assert:
that:
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }}']
- result.rowcount == [3]
- result.query_result[0][0].id == 1
- result.query_result[0][1].id == 2
- result.query_result[0][2].id == 3
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }}']
- result.rowcount == [3]
- result.query_result[0][0].id == 1
- result.query_result[0][1].id == 2
- result.query_result[0][2].id == 3
- name: Check data in {{ test_table1 }} using positional args
mysql_query:
@ -76,10 +76,10 @@
- assert:
that:
- result is not changed
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
- result.rowcount == [1]
- result.query_result[0][0].id == 1
- result is not changed
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
- result.rowcount == [1]
- result.query_result[0][0].id == 1
- name: Check data in {{ test_table1 }} using named args
mysql_query:
@ -92,10 +92,10 @@
- assert:
that:
- result is not changed
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
- result.rowcount == [1]
- result.query_result[0][0].id == 1
- result is not changed
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
- result.rowcount == [1]
- result.query_result[0][0].id == 1
- name: Update data in {{ test_table1 }}
mysql_query:
@ -109,9 +109,9 @@
- assert:
that:
- result is changed
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
- result.rowcount == [1]
- result is changed
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
- result.rowcount == [1]
- name: Check the prev update - row with value 1 does not exist anymore
mysql_query:
@ -124,9 +124,9 @@
- assert:
that:
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1']
- result.rowcount == [0]
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1']
- result.rowcount == [0]
- name: Check the prev update - row with value - exist
mysql_query:
@ -139,9 +139,9 @@
- assert:
that:
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [1]
- result is not changed
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [1]
- name: Update data in {{ test_table1 }} again
mysql_query:
@ -155,9 +155,9 @@
- assert:
that:
- result is not changed
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
- result.rowcount == [0]
- result is not changed
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
- result.rowcount == [0]
- name: Delete data from {{ test_table1 }}
mysql_query:
@ -170,9 +170,9 @@
- assert:
that:
- result is changed
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [1, 0]
- result is changed
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [1, 0]
- name: Delete data from {{ test_table1 }} again
mysql_query:
@ -183,9 +183,9 @@
- assert:
that:
- result is not changed
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [0]
- result is not changed
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0']
- result.rowcount == [0]
- name: Truncate {{ test_table1 }}
mysql_query:
@ -198,9 +198,9 @@
- assert:
that:
- result is changed
- result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}']
- result.rowcount == [0, 0]
- result is changed
- result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}']
- result.rowcount == [0, 0]
- name: Rename {{ test_table1 }}
mysql_query:
@ -211,9 +211,9 @@
- assert:
that:
- result is changed
- result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}']
- result.rowcount == [0]
- result is changed
- result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}']
- result.rowcount == [0]
- name: Check the prev rename
mysql_query:
@ -225,7 +225,7 @@
- assert:
that:
- result.failed == true
- result is failed
- name: Check the prev rename
mysql_query:
@ -236,7 +236,7 @@
- assert:
that:
- result.rowcount == [0]
- result.rowcount == [0]
- name: Create {{ test_table3 }}
mysql_query:
@ -259,7 +259,7 @@
- assert:
that:
- result.rowcount == [2]
- result.rowcount == [2]
- name: Pass wrong query type
mysql_query:
@ -271,8 +271,8 @@
- assert:
that:
- result is failed
- result.msg is search('the query option value must be a string or list')
- result is failed
- result.msg is search('the query option value must be a string or list')
- name: Pass wrong query element
mysql_query:
@ -286,8 +286,73 @@
- assert:
that:
- result is failed
- result.msg is search('the elements in query list must be strings')
- result is failed
- result.msg is search('the elements in query list must be strings')
- name: Create {{ test_table4 }}
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: 'CREATE TABLE {{ test_table4 }} (id int primary key, story text)'
- name: Insert test data using replace statement
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "REPLACE INTO {{ test_table4 }} VALUES (1, 'first')"
single_transaction: yes
register: result
- assert:
that:
- result is changed
- result.rowcount == [1]
- name: Replace test data
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "REPLACE INTO {{ test_table4 }} VALUES (1, 'one')"
single_transaction: yes
register: result
- assert:
that:
- result is changed
- result.rowcount == [2]
# Issue https://github.com/ansible-collections/community.mysql/issues/268
- name: Create table
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "CREATE TABLE issue268 (id int)"
single_transaction: yes
# Issue https://github.com/ansible-collections/community.mysql/issues/268
- name: Create table with IF NOT EXISTS
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "CREATE TABLE IF NOT EXISTS issue268 (id int)"
single_transaction: yes
register: result
# Issue https://github.com/ansible-collections/community.mysql/issues/268
- assert:
that:
# PyMySQL driver throws a warning, so the following is correct
- result is not changed
when: connector_name is search('pymysql')
# Issue https://github.com/ansible-collections/community.mysql/issues/268
- assert:
that:
# mysqlclient driver throws nothing, so it's impossible to figure out
# if the state was changed or not.
# We assume that it was for DDL queryes by default in the code
- result is changed
when: connector_name is search('mysqlclient')
- name: Drop db {{ test_db }}
mysql_query:
@ -297,5 +362,5 @@
- assert:
that:
- result is changed
- result.executed_queries == ['DROP DATABASE {{ test_db }}']
- result is changed
- result.executed_queries == ['DROP DATABASE {{ test_db }}']

View file

@ -1,16 +1,24 @@
---
- name: alias mysql command to include default options
set_fact:
mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} -P{{ mysql_primary_port }} --protocol=tcp"
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -48,12 +56,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_replication:

View file

@ -14,6 +14,8 @@
# Tests of channel parameter:
- import_tasks: mysql_replication_channel.yml
when:
- install_type == 'mysql' # FIXME: mariadb introduces FOR CHANNEL in 10.7
# Tests of resetmaster mode:
- import_tasks: mysql_replication_resetmaster_mode.yml

View file

@ -24,14 +24,20 @@
mysql8022_and_higher: true
when:
- db.version.major > 8 or (db.version.major == 8 and db.version.minor > 0) or (db.version.major == 8 and db.version.minor == 0 and db.version.release >= 22)
- install_type == 'mysql'
- name: alias mysql command to include default options
set_fact:
mysql_command: "mysql -u{{ mysql_user }} -p{{ mysql_password }} --protocol=tcp"
# Preparation:
- name: Create user for replication
- name: Create user for mysql replication
shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED WITH mysql_native_password BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}"
when: install_type == 'mysql'
- name: Create user for mariadb replication
shell: "echo \"CREATE USER '{{ replication_user }}'@'localhost' IDENTIFIED BY '{{ replication_pass }}'; GRANT REPLICATION SLAVE ON *.* TO '{{ replication_user }}'@'localhost';\" | {{ mysql_command }} -P{{ mysql_primary_port }}"
when: install_type == 'mariadb'
- name: Create test database
mysql_db:
@ -176,8 +182,8 @@
shell: "echo \"INSERT INTO {{ test_table }} (id) VALUES (1), (2), (3); FLUSH LOGS;\" | {{ mysql_command }} -P{{ mysql_primary_port }} {{ test_db }}"
- name: Small pause to be sure the bin log, which was flushed previously, reached the replica
pause:
seconds: 2
ansible.builtin.wait_for:
timeout: 2
# Test master log pos has been changed:
- name: Get replica status
@ -199,9 +205,6 @@
- replica_status.Exec_Source_Log_Pos != mysql_primary_status.Position
when: mysql8022_and_higher == true
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: Start replica that is already running
mysql_replication:
<<: *mysql_params
@ -210,10 +213,12 @@
fail_on_error: true
register: result
# mysqlclient 2.0.1 always return "changed"
- assert:
that:
- result is not changed
when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=')
- result is not changed
when:
- connector_name == 'pymysql'
# Test stopreplica mode:
- name: Stop replica using deprecated stopslave choice
@ -228,7 +233,12 @@
- result is changed
- result.queries == ["STOP SLAVE"] or result.queries == ["STOP REPLICA"]
- name: Pause for 2 seconds to let the replication stop
ansible.builtin.wait_for:
timeout: 2
# Test stopreplica mode:
# mysqlclient 2.0.1 always return "changed"
- name: Stop replica that is no longer running
mysql_replication:
<<: *mysql_params
@ -239,5 +249,6 @@
- assert:
that:
- result is not changed
when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=')
- result is not changed
when:
- connector_name == 'pymysql'

View file

@ -0,0 +1,24 @@
- name: "applying user {{ username }}@{{ host }} with update_password={{ update_password }}"
mysql_user:
login_user: '{{ mysql_parameters.login_user }}'
login_password: '{{ mysql_parameters.login_password }}'
login_host: '{{ mysql_parameters.login_host }}'
login_port: '{{ mysql_parameters.login_port }}'
state: present
name: "{{ username }}"
host: "{{ host }}"
password: "{{ password }}"
update_password: "{{ update_password }}"
register: result
- name: assert a change occurred
assert:
that:
- "result.changed | bool == {{ expect_change }} | bool"
- "result.password_changed == {{ expect_password_change }}"
- name: query the user
command: "{{ mysql_command }} -BNe \"SELECT plugin, authentication_string FROM mysql.user where user='{{ username }}' and host='{{ host }}'\""
register: existing_user
- name: assert the password is as set to expect_hash
assert:
that:
- "'mysql_native_password\t{{ expect_password_hash }}' in existing_user.stdout_lines"

View file

@ -37,4 +37,4 @@
- name: assert output message mysql user was created
assert:
that:
- "result.changed == true"
- result is changed

View file

@ -9,8 +9,6 @@
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:

View file

@ -1,16 +1,20 @@
---
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -50,12 +54,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_user:

View file

@ -17,7 +17,9 @@
register: result
- name: assert root password is changed
assert: { that: "result.changed == true" }
assert:
that:
- result is changed
- name: Set root password again
mysql_user:
@ -31,7 +33,9 @@
register: result
- name: Assert root password is not changed
assert: { that: "result.changed == false" }
assert:
that:
- result is not changed
- name: Set root password again
mysql_user:

View file

@ -65,7 +65,9 @@
register: result
- name: assert output message mysql user was not created
assert: { that: "result.changed == false" }
assert:
that:
- result is not changed
# ============================================================
# remove mysql user and verify user is removed from mysql database
@ -81,7 +83,7 @@
- name: assert output message mysql user was removed
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_no_user.yml user_name={{user_name_1}}
@ -99,7 +101,7 @@
- name: assert output message mysql user that does not exist
assert:
that:
- "result.changed == false"
- result is not changed
- include: assert_no_user.yml user_name={{user_name_1}}
@ -242,7 +244,9 @@
# ============================================================
# Test plugin authentication scenarios.
#
# FIXME: mariadb sql syntax for create/update user is not compatible
- include: test_user_plugin_auth.yml
when: install_type == 'mysql'
# ============================================================
# Assert create user with SELECT privileges, attempt to create database and update privileges to create database
@ -282,3 +286,6 @@
- import_tasks: issue-64560.yaml
tags:
- issue-64560
# https://github.com/ansible-collections/community.mysql/issues/231
- include: test_user_grants_with_roles_applied.yml

View file

@ -37,7 +37,7 @@
- name: assert output message mysql user was removed
assert:
that:
- "result.changed == true"
- result is changed
# ============================================================
- name: create blank mysql user to be removed later
@ -58,7 +58,7 @@
- name: assert changed is true for removing all blank users
assert:
that:
- "result.changed == true"
- result is changed
- name: remove blank mysql user with hosts=all (expect ok)
mysql_user:
@ -71,4 +71,4 @@
- name: assert changed is true for removing all blank users
assert:
that:
- "result.changed == false"
- result is not changed

View file

@ -50,7 +50,7 @@
- name: Assert that there wasn't a change in permissions
assert:
that:
- "result.changed == false"
- result is not changed
- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\""
@ -76,7 +76,7 @@
- name: Assert that there was a change because permissions were added to data1.*
assert:
that:
- "result.changed == true"
- result is changed
- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_4 }}'@'localhost'\""

View file

@ -51,7 +51,7 @@
- name: assert output message for current privileges
assert:
that:
- "result.changed == true"
- result is changed
- name: run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{user_name_2}}'@'localhost'\""
@ -101,7 +101,7 @@
- name: Assert that priv changed
assert:
that:
- "result.changed == true"
- result is changed
- name: Add privs to a specific table (expect ok)
mysql_user:
@ -115,7 +115,7 @@
- name: Assert that priv did not change
assert:
that:
- "result.changed == false"
- result is not changed
# ============================================================
- name: update user with all privileges
@ -162,7 +162,7 @@
- name: Assert that priv changed
assert:
that:
- "result.changed == true"
- result is changed
- name: Test idempotency (expect ok)
mysql_user:
@ -176,7 +176,24 @@
- name: Assert that priv did not change
assert:
that:
- "result.changed == false"
- result is not changed
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.2', '=='))
# ============================================================
- name: update user with invalid privileges
mysql_user:
<<: *mysql_params
name: '{{ user_name_2 }}'
password: '{{ user_password_2 }}'
priv: '*.*:INVALID'
state: present
register: result
ignore_errors: yes
- name: Assert that priv did not change
assert:
that:
- result is failed
- name: remove username
mysql_user:

View file

@ -0,0 +1,98 @@
# https://github.com/ansible-collections/community.mysql/issues/231
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
block:
- name: Get server version
mysql_info:
<<: *mysql_params
register: srv
# Skip unsupported versions
- meta: end_play
when: srv['version']['major'] < 8
- name: Create test databases
mysql_db:
<<: *mysql_params
name: '{{ item }}'
state: present
loop:
- data1
- data2
- name: Create user with privileges
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
password: '{{ user_password_3 }}'
priv:
"data1.*": "SELECT"
"data2.*": "SELECT"
state: present
- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\""
register: result
- name: Assert user has giving privileges
assert:
that:
- "'GRANT SELECT ON `data1`.*' in result.stdout"
- "'GRANT SELECT ON `data2`.*' in result.stdout"
- name: Create role
mysql_query:
<<: *mysql_params
query: CREATE ROLE IF NOT EXISTS test231
- name: Grant role
mysql_query:
<<: *mysql_params
query: 'GRANT test231 TO {{ user_name_3 }}@localhost'
- name: Try to change privs
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
priv:
"data1.*": "INSERT"
"data2.*": "INSERT"
state: present
- name: Run command to show privileges for user (expect privileges in stdout)
command: "{{ mysql_command }} -e \"SHOW GRANTS FOR '{{ user_name_3 }}'@'localhost'\""
register: result
- name: Assert user has giving privileges
assert:
that:
- "'GRANT INSERT ON `data1`.*' in result.stdout"
- "'GRANT INSERT ON `data2`.*' in result.stdout"
##########
# Clean up
- name: Drop test databases
mysql_db:
<<: *mysql_params
name: '{{ item }}'
state: present
loop:
- data1
- data2
- name: Drop test user
mysql_user:
<<: *mysql_params
name: '{{ user_name_3 }}'
state: absent
- name: Drop test role
mysql_query:
<<: *mysql_params
query: DROP ROLE IF EXISTS test231

View file

@ -32,7 +32,7 @@
- name: Assert that a change occurred because the user was added
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -49,7 +49,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Run mysql_user again without any changes
mysql_user:
@ -63,7 +63,7 @@
- name: Assert that there weren't any changes because username/password didn't change
assert:
that:
- "result.changed == false"
- result is not changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -78,7 +78,7 @@
- name: Assert that a change occurred because the password was updated
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -95,7 +95,7 @@
- name: Assert that the mysql_info module failed because we used the old password
assert:
that:
- "result.failed == true"
- result is failed
- name: Get the MySQL version data using the new password (should work)
mysql_info:
@ -110,7 +110,7 @@
- name: Assert that the mysql_info module succeeded because we used the new password
assert:
that:
- "result.failed == false"
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }}
@ -131,7 +131,7 @@
- name: Assert that a change occurred because the user was added
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -148,7 +148,7 @@
- name: Assert that there weren't any changes because username/password didn't change
assert:
that:
- "result.changed == false"
- result is not changed
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }}
@ -170,7 +170,7 @@
- name: Assert that a change occurred because the user was added
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -187,7 +187,7 @@
- name: Assert that the mysql_info module succeeded because we used the new password
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Pass in the same password as before, but in the encrypted form (no change expected)
mysql_user:
@ -200,7 +200,7 @@
- name: Assert that there weren't any changes because username/password didn't change
assert:
that:
- "result.changed == false"
- result is not changed
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ new_password }}
@ -220,7 +220,7 @@
- name: Assert that a change occurred because the user was added
assert:
that:
- "result.changed == true"
- result is changed
- name: Get the MySQL version using an empty password for the newly created user
mysql_info:
@ -235,7 +235,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Get the MySQL version using an non-empty password (should fail)
mysql_info:
@ -250,7 +250,7 @@
- name: Assert that mysql_info failed
assert:
that:
- "result.failed == true"
- result is failed
- name: Update the user without changing the password
mysql_user:
@ -263,7 +263,7 @@
- name: Assert that the user wasn't changed because the password is still empty
assert:
that:
- "result.changed == false"
- result is not changed
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password=''

View file

@ -31,14 +31,19 @@
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "result.changed == true"
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -54,7 +59,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Update the user with a different hash
mysql_user:
@ -67,7 +72,7 @@
- name: Check that the module makes the change because the hash changed
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -83,7 +88,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_new_auth_string }}
@ -102,14 +107,19 @@
register: result
- name: Get user information
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
command: "{{ mysql_command }} -e \"SELECT user, host, plugin FROM mysql.user WHERE user = '{{ test_user_name }}' and host = 'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "result.changed == true"
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -125,7 +135,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Update the user with the same hash (no change expected)
mysql_user:
@ -135,10 +145,12 @@
plugin_hash_string: '{{ test_plugin_hash }}'
register: result
# FIXME: on mariadb 10.2 there's always a change
- name: Check that the module doesn't make a change when the same hash is passed in
assert:
that:
- "result.changed == false"
- result is not changed
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -154,7 +166,7 @@
- name: Check that the module did not change the password
assert:
that:
- "result.changed == true"
- result is changed
- name: Getting the MySQL info should still work
mysql_info:
@ -168,7 +180,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
@ -190,11 +202,16 @@
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "result.changed == true"
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -210,7 +227,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Update the user with the same auth string
mysql_user:
@ -225,7 +242,7 @@
- name: The module should detect a change even though the password is the same
assert:
that:
- "result.changed == true"
- result is changed
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -240,7 +257,7 @@
- name: Check that the module did not change the password
assert:
that:
- "result.changed == false"
- result is not changed
- name: Get the MySQL version using the newly created creds
mysql_info:
@ -254,7 +271,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
@ -275,11 +292,16 @@
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "result.changed == true"
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -296,7 +318,7 @@
- name: Assert that mysql_info was successful
assert:
that:
- "result.failed == false"
- result is succeeded
- name: Get the MySQL version using an non-empty password (should fail)
mysql_info:
@ -311,7 +333,7 @@
- name: Assert that mysql_info failed
assert:
that:
- "result.failed == true"
- result is failed
- name: Update the user without changing the auth mechanism
mysql_user:
@ -324,7 +346,7 @@
- name: Assert that the user wasn't changed because the auth string is still empty
assert:
that:
- "result.changed == false"
- result is not changed
# Cleanup
- include: remove_user.yml user_name={{ test_user_name }} user_password={{ test_plugin_auth_string }}
@ -334,12 +356,14 @@
# plugins that are loaded by default are sha2*, but these aren't compatible with pymysql < 0.9, so skip these tests
# for those versions.
#
- name: Get pymysql version
shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: Test plugin auth switching which doesn't work on pymysql < 0.9
when: pymysql_version.stdout == "" or (pymysql_version.stdout != "" and pymysql_version.stdout is version('0.9', '>='))
when:
- >
connector_name is not search('pymysql')
or (
connector_name is search('pymysql')
and connector_ver is version('0.9', '>=')
)
block:
- name: Create user with plugin auth (empty auth string)
@ -354,11 +378,16 @@
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "result.changed == true"
- "'{{ test_plugin_type }}' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}
@ -374,11 +403,16 @@
command: "{{ mysql_command }} -e \"SHOW CREATE USER '{{ test_user_name }}'@'localhost'\""
register: show_create_user
- name: Check that the module made a change and that the expected plugin type is set
- name: Check that the module made a change
assert:
that:
- "result.changed == true"
- "'sha256_password' in show_create_user.stdout"
- result is changed
- name: Check that the expected plugin type is set
assert:
that:
- "'sha256_password' in show_create_user.stdout"
when: install_type == 'mysql' or (install_type == 'mariadb' and mariadb_version is version('10.3', '>='))
- include: assert_user.yml user_name={{ test_user_name }} priv={{ test_default_priv_type }}

View file

@ -55,7 +55,7 @@
issuer: '/CN=org/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
- block:
- name: retrieve TLS requiremets for users in old database version
- name: retrieve TLS requirements for users in old database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ item }}'@'localhost'\""
register: old_result
with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}']
@ -67,7 +67,7 @@
when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2
- block:
- name: retrieve TLS requiremets for users in new database version
- name: retrieve TLS requirements for users in new database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ item }}'@'localhost'\""
register: new_result
with_items: ['{{ user_name_1 }}', '{{ user_name_2 }}', '{{ user_name_3 }}']
@ -119,12 +119,12 @@
that:
- result is changed
- name: retrieve TLS requiremets for users in old database version
- name: retrieve TLS requirements for users in old database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\""
register: old_result
when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2
- name: retrieve TLS requiremets for users in new database version
- name: retrieve TLS requirements for users in new database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\""
register: new_result
when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2
@ -143,12 +143,12 @@
tls_requires:
X509:
- name: retrieve TLS requiremets for users in old database version
- name: retrieve TLS requirements for users in old database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\""
register: old_result
when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2
- name: retrieve TLS requiremets for users in new database version
- name: retrieve TLS requirements for users in new database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW CREATE USER '{{ user_name_1 }}'@'localhost'\""
register: new_result
when: db_version.version.major == 5 and db_version.version.minor >= 7 or db_version.version.major > 5 and db_version.version.major < 10 or db_version.version.major == 10 and db_version.version.minor >= 2
@ -159,28 +159,20 @@
vars:
- reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip()}}"
- name: remove TLS requiremets from user (expect changed=true)
- name: remove TLS requirements from user (expect changed=true)
mysql_user:
<<: *mysql_params
name: '{{ user_name_1 }}'
password: '{{ user_password_1 }}'
tls_requires:
- name: retrieve TLS requiremets for users in old database version
command: "{{ mysql_command }} -L -N -s -e \"SHOW GRANTS for '{{ user_name_1 }}'@'localhost'\""
register: old_result
when: db_version.version.major <= 5 and db_version.version.minor <= 6 or db_version.version.major == 10 and db_version.version.minor < 2
- name: retrieve TLS requiremets for users in new database version
- name: retrieve TLS requirements for users
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
register: result
- name: assert user1 TLS requirements
assert:
that: "'NONE' in reqs"
vars:
- reqs: "{{(old_result is skipped | ternary(new_result, old_result)).stdout.split('REQUIRE')[1].split(separator)[0].strip() | default('NONE') }}"
that: "'REQUIRE ' not in result.stdout or 'REQUIRE NONE' in result.stdout"
- include: remove_user.yml user_name={{user_name_1}} user_password={{ user_password_1 }}

View file

@ -22,4 +22,4 @@
- name: assert message failure (expect failed=true)
assert:
that:
- "output.failed == true"
- output is failed

View file

@ -22,7 +22,7 @@
- name: assert output message changed value
assert:
that:
- "output.changed == {{ changed }}"
- "output.changed | bool == changed | bool"
- name: run mysql command to show variable
command: "{{ mysql_command }} \"-e show variables like '{{ var_name }}'\""
@ -31,6 +31,6 @@
- name: assert output mysql variable name and value
assert:
that:
- "result.changed == true"
- result is changed
- "'{{ var_name }}' in result.stdout"
- "'{{ var_value }}' in result.stdout"

View file

@ -22,7 +22,7 @@
- name: assert output message changed value
assert:
that:
- "output.changed == {{ changed }}"
- "output.changed | bool == changed | bool"
- set_fact:
key_name: "{{ var_name }}"
@ -35,6 +35,6 @@
- name: assert output variable info match mysql variable info
assert:
that:
- "result.changed == true"
- result is changed
- "key_name in result.stdout"
- "key_value in result.stdout"

View file

@ -1,16 +1,20 @@
---
- name: set fact tls_enabled
command: "{{ mysql_command }} \"-e SHOW VARIABLES LIKE 'have_ssl';\""
register: result
- set_fact:
tls_enabled: "{{ 'YES' in result.stdout | bool | default('false', true) }}"
- vars:
mysql_parameters: &mysql_params
login_user: '{{ mysql_user }}'
login_password: '{{ mysql_password }}'
login_host: 127.0.0.1
login_port: '{{ mysql_primary_port }}'
when: tls_enabled
block:
# ============================================================
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: get server certificate
copy:
@ -48,12 +52,12 @@
- assert:
that:
- result is failed
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
- assert:
that:
- result is succeeded
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- name: attempt connection with newly created user ignoring hostname
mysql_variables:

View file

@ -151,22 +151,19 @@
# ============================================================
# Verify mysql_variable fails when setting an incorrect value (out of range)
#
- shell: pip show pymysql | awk '/Version/ {print $2}'
register: pymysql_version
- name: set mysql variable value to a number out of range
mysql_variables:
<<: *mysql_params
variable: max_connect_errors
value: -1
value: '-1'
register: oor_result
ignore_errors: true
- include: assert_var.yml changed=true output={{ oor_result }} var_name=max_connect_errors var_value=1
when: pymysql_version.stdout == ""
when: connector_name is not search('pymysql')
- include: assert_fail_msg.yml output={{ oor_result }} msg='Truncated incorrect'
when: pymysql_version.stdout != ""
when: connector_name is search('pymysql')
# ============================================================
# Verify mysql_variable fails when setting an incorrect value (incorrect type)
@ -362,7 +359,9 @@
- include: assert_var.yml changed=true output={{ result }} var_name={{ set_name }} var_value='{{ def_val }}'
when: mysql_version is not version('8.0', '<')
when:
- mysql_version is version('8.0', '>=')
- install_type == 'mysql'
# Bugfix of https://github.com/ansible/ansible/issues/54239
# - name: set variable containing dot

View file

@ -0,0 +1,8 @@
plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen
plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_user.py validate-modules:undocumented-parameter
plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch

View file

@ -0,0 +1,8 @@
plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen
plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_user.py validate-modules:undocumented-parameter
plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch

View file

@ -0,0 +1,8 @@
plugins/modules/mysql_db.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_db.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen
plugins/modules/mysql_info.py validate-modules:doc-elements-mismatch
plugins/modules/mysql_info.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_query.py validate-modules:parameter-list-no-elements
plugins/modules/mysql_user.py validate-modules:undocumented-parameter
plugins/modules/mysql_variables.py validate-modules:doc-required-mismatch