mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-06-19 06:40:23 -07:00
Compare commits
25 commits
Author | SHA1 | Date | |
---|---|---|---|
|
67f1460070 | ||
|
fa3c72b2c0 | ||
|
49be739e89 | ||
|
7307a51f20 | ||
|
06e23c8ac3 | ||
|
74ea0438ce | ||
|
d44f8f2039 | ||
|
da2dc9ab5d | ||
|
b26235b7d7 | ||
|
45a29408ad | ||
|
dd7e297d50 | ||
|
e9845b0a1c | ||
|
960ac32adf | ||
|
a45a0d006d | ||
|
022ed60906 | ||
|
3d3f115574 | ||
|
e437d562c1 | ||
|
9057637844 | ||
|
d613fa1993 | ||
|
7d787eb238 | ||
|
ebb37ae7a3 | ||
|
90bd0b0a75 | ||
|
93cd1850d9 | ||
|
a5afa1a375 | ||
|
28bf7093be |
46 changed files with 1250 additions and 356 deletions
26
.github/workflows/ansible-test-plugins.yml
vendored
26
.github/workflows/ansible-test-plugins.yml
vendored
|
@ -13,7 +13,7 @@ on: # yamllint disable-line rule:truthy
|
||||||
- '.github/workflows/ansible-test-plugins.yml'
|
- '.github/workflows/ansible-test-plugins.yml'
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 6 * * *'
|
- cron: '0 6 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
sanity:
|
sanity:
|
||||||
|
@ -22,9 +22,9 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ansible:
|
ansible:
|
||||||
- stable-2.15
|
|
||||||
- stable-2.16
|
- stable-2.16
|
||||||
- stable-2.17
|
- stable-2.17
|
||||||
|
- stable-2.18
|
||||||
- devel
|
- devel
|
||||||
steps:
|
steps:
|
||||||
# https://github.com/ansible-community/ansible-test-gh-action
|
# https://github.com/ansible-community/ansible-test-gh-action
|
||||||
|
@ -44,9 +44,9 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ansible:
|
ansible:
|
||||||
- stable-2.15
|
|
||||||
- stable-2.16
|
- stable-2.16
|
||||||
- stable-2.17
|
- stable-2.17
|
||||||
|
- stable-2.18
|
||||||
- devel
|
- devel
|
||||||
db_engine_name:
|
db_engine_name:
|
||||||
- mysql
|
- mysql
|
||||||
|
@ -54,8 +54,8 @@ jobs:
|
||||||
db_engine_version:
|
db_engine_version:
|
||||||
- '8.0.38'
|
- '8.0.38'
|
||||||
- '8.4.1'
|
- '8.4.1'
|
||||||
- '10.5.25'
|
|
||||||
- '10.11.8'
|
- '10.11.8'
|
||||||
|
- '11.4.5'
|
||||||
connector_name:
|
connector_name:
|
||||||
- pymysql
|
- pymysql
|
||||||
- mysqlclient
|
- mysqlclient
|
||||||
|
@ -87,10 +87,10 @@ jobs:
|
||||||
exclude:
|
exclude:
|
||||||
|
|
||||||
- db_engine_name: mysql
|
- db_engine_name: mysql
|
||||||
db_engine_version: '10.5.25'
|
db_engine_version: '10.11.8'
|
||||||
|
|
||||||
- db_engine_name: mysql
|
- db_engine_name: mysql
|
||||||
db_engine_version: '10.11.8'
|
db_engine_version: '11.4.5'
|
||||||
|
|
||||||
- db_engine_name: mariadb
|
- db_engine_name: mariadb
|
||||||
db_engine_version: '8.0.38'
|
db_engine_version: '8.0.38'
|
||||||
|
@ -119,13 +119,13 @@ jobs:
|
||||||
- db_engine_version: '8.0.38'
|
- db_engine_version: '8.0.38'
|
||||||
ansible: stable-2.17
|
ansible: stable-2.17
|
||||||
|
|
||||||
- db_engine_version: '10.5.25'
|
- db_engine_version: '10.11.8'
|
||||||
ansible: stable-2.17
|
ansible: stable-2.17
|
||||||
|
|
||||||
- db_engine_version: '8.0.38'
|
- db_engine_version: '8.0.38'
|
||||||
ansible: devel
|
ansible: devel
|
||||||
|
|
||||||
- db_engine_version: '10.5.25'
|
- db_engine_version: '10.11.8'
|
||||||
ansible: devel
|
ansible: devel
|
||||||
|
|
||||||
- db_engine_version: '8.4.1'
|
- db_engine_version: '8.4.1'
|
||||||
|
@ -162,7 +162,7 @@ jobs:
|
||||||
db_engine_version: '8.0.38'
|
db_engine_version: '8.0.38'
|
||||||
|
|
||||||
- connector_version: '1.1.1'
|
- connector_version: '1.1.1'
|
||||||
db_engine_version: '10.5.25'
|
db_engine_version: '10.11.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db_primary:
|
db_primary:
|
||||||
|
@ -175,7 +175,7 @@ jobs:
|
||||||
# We write our own health-cmd because the mariadb container does not
|
# We write our own health-cmd because the mariadb container does not
|
||||||
# provide a healthcheck
|
# provide a healthcheck
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
|
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
|
||||||
--health-start-period 10s
|
--health-start-period 10s
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
|
@ -189,7 +189,7 @@ jobs:
|
||||||
ports:
|
ports:
|
||||||
- 3308:3306
|
- 3308:3306
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
|
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
|
||||||
--health-start-period 10s
|
--health-start-period 10s
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
|
@ -203,7 +203,7 @@ jobs:
|
||||||
ports:
|
ports:
|
||||||
- 3309:3306
|
- 3309:3306
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
|
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
|
||||||
--health-start-period 10s
|
--health-start-period 10s
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
|
@ -282,9 +282,9 @@ jobs:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
ansible:
|
ansible:
|
||||||
- stable-2.15
|
|
||||||
- stable-2.16
|
- stable-2.16
|
||||||
- stable-2.17
|
- stable-2.17
|
||||||
|
- stable-2.18
|
||||||
- devel
|
- devel
|
||||||
python:
|
python:
|
||||||
- '3.8'
|
- '3.8'
|
||||||
|
|
|
@ -6,6 +6,85 @@ Community MySQL and MariaDB Collection Release Notes
|
||||||
|
|
||||||
This changelog describes changes after version 2.0.0.
|
This changelog describes changes after version 2.0.0.
|
||||||
|
|
||||||
|
v3.14.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_replication - change default value for ``primary_ssl_verify_server_cert`` from False to None. This should not affect existing playbooks (https://github.com/ansible-collections/community.mysql/pull/707).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- mysql_info - fix a crash (ERROR 1141, There is no such grant defined for user 'PUBLIC' on host '%') when using the ``users_info`` filter with a PUBLIC role present in MariaDB 10.11+. Do note that the fix doesn't change the fact that the module won't return the privileges from the PUBLIC role in the users privileges list. It can't do that because you have to login as the particular user and use `SHOW GRANTS FOR CURRENT_USER`. We considered using an aggregation with the `SHOW GRANTS FOR PUBLIC` command. However, this approach would make copying users from one server to another transform the privileges inherited from the role as if they were direct privileges on the user.
|
||||||
|
- mysql_replication - fixed an issue where setting ``primary_ssl_verify_server_cert`` to false had no effect (https://github.com/ansible-collections/community.mysql/issues/689).
|
||||||
|
|
||||||
|
v3.13.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
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Integration tests for MariaDB 11.4 have replaced those for 10.5. The previous version is now 10.11.
|
||||||
|
- mysql_user - add ``locked`` option to lock/unlock users, this is mainly used to have users that will act as definers on stored procedures.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- mysql_db - fix dump and import to find MariaDB binaries (mariadb and mariadb-dump) when MariaDB 11+ is used and symbolic links to MySQL binaries are absent.
|
||||||
|
|
||||||
|
v3.12.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_db - added ``zstd`` (de)compression support for ``import``/``dump`` states (https://github.com/ansible-collections/community.mysql/issues/696).
|
||||||
|
- mysql_query - returns the ``execution_time_ms`` list containing execution time per query in milliseconds.
|
||||||
|
|
||||||
|
v3.11.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 - adds the count of tables for each database to the returned values. It is possible to exclude this new field using the ``db_table_count`` exclusion filter. (https://github.com/ansible-collections/community.mysql/pull/691)
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- mysql_user,mysql_role - The sql_mode ANSI_QUOTES affects how the modules mysql_user and mysql_role compare the existing privileges with the configured privileges, as well as decide whether double quotes or backticks should be used in the GRANT statements. Pointing out in issue 671, the modules mysql_user and mysql_role allow users to enable/disable ANSI_QUOTES in session variable (within a DB session, the session variable always overwrites the global one). But due to the issue, the modules do not check for ANSI_MODE in the session variable, instead, they only check in the GLOBAL one.That behavior is not only limiting the users' flexibility, but also not allowing users to explicitly disable ANSI_MODE to work around such bugs like https://bugs.mysql.com/bug.php?id=115953. (https://github.com/ansible-collections/community.mysql/issues/671)
|
||||||
|
|
||||||
v3.10.3
|
v3.10.3
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -45,8 +124,8 @@ Release Summary
|
||||||
This is a patch release of the ``community.mysql`` collection.
|
This is a patch release of the ``community.mysql`` collection.
|
||||||
Besides a bugfix, it contains an important upcoming breaking-change information.
|
Besides a bugfix, it contains an important upcoming breaking-change information.
|
||||||
|
|
||||||
Breaking Changes / Porting Guide
|
Deprecated Features
|
||||||
--------------------------------
|
-------------------
|
||||||
|
|
||||||
- mysql_user - the ``user`` alias of the ``name`` argument has been deprecated and will be removed in collection version 5.0.0. Use the ``name`` argument instead.
|
- mysql_user - the ``user`` alias of the ``name`` argument has been deprecated and will be removed in collection version 5.0.0. Use the ``name`` argument instead.
|
||||||
|
|
||||||
|
@ -75,8 +154,8 @@ Minor Changes
|
||||||
- mysql_replication - Improve detection of IsReplica and IsPrimary by inspecting the dictionary returned from the SQL query instead of relying on variable types. This ensures compatibility with changes in the connector or the output of SHOW REPLICA STATUS and SHOW MASTER STATUS, allowing for easier maintenance if these change in the future.
|
- mysql_replication - Improve detection of IsReplica and IsPrimary by inspecting the dictionary returned from the SQL query instead of relying on variable types. This ensures compatibility with changes in the connector or the output of SHOW REPLICA STATUS and SHOW MASTER STATUS, allowing for easier maintenance if these change in the future.
|
||||||
- mysql_user - Add salt parameter to generate static hash for `caching_sha2_password` and `sha256_password` plugins.
|
- mysql_user - Add salt parameter to generate static hash for `caching_sha2_password` and `sha256_password` plugins.
|
||||||
|
|
||||||
Breaking Changes / Porting Guide
|
Deprecated Features
|
||||||
--------------------------------
|
-------------------
|
||||||
|
|
||||||
- collection - support of mysqlclient connector is deprecated - use PyMySQL connector instead! We will stop testing against it in collection version 4.0.0 and remove the related code in 5.0.0 (https://github.com/ansible-collections/community.mysql/issues/654).
|
- collection - support of mysqlclient connector is deprecated - use PyMySQL connector instead! We will stop testing against it in collection version 4.0.0 and remove the related code in 5.0.0 (https://github.com/ansible-collections/community.mysql/issues/654).
|
||||||
- mysql_info - The ``users_info`` filter returned variable ``plugin_auth_string`` contains the hashed password and it's misleading, it will be removed from community.mysql 4.0.0. Use the `plugin_hash_string` return value instead (https://github.com/ansible-collections/community.mysql/pull/629).
|
- mysql_info - The ``users_info`` filter returned variable ``plugin_auth_string`` contains the hashed password and it's misleading, it will be removed from community.mysql 4.0.0. Use the `plugin_hash_string` return value instead (https://github.com/ansible-collections/community.mysql/pull/629).
|
||||||
|
|
36
CONTRIBUTORS
36
CONTRIBUTORS
|
@ -17,9 +17,11 @@ amitk79
|
||||||
amree
|
amree
|
||||||
Andersson007
|
Andersson007
|
||||||
andrewhowdencom
|
andrewhowdencom
|
||||||
|
aneustroev
|
||||||
ansibot
|
ansibot
|
||||||
anthonyxpalermo
|
anthonyxpalermo
|
||||||
antonioribeiro
|
antonioribeiro
|
||||||
|
Aohzan
|
||||||
apollo13
|
apollo13
|
||||||
aquach
|
aquach
|
||||||
arcmop
|
arcmop
|
||||||
|
@ -33,6 +35,8 @@ baldpale
|
||||||
banyek
|
banyek
|
||||||
BarbzYHOOL
|
BarbzYHOOL
|
||||||
Berbe
|
Berbe
|
||||||
|
betanummeric
|
||||||
|
bigo8525
|
||||||
bizmate
|
bizmate
|
||||||
bjne
|
bjne
|
||||||
bmalynovytch
|
bmalynovytch
|
||||||
|
@ -46,6 +50,7 @@ candeira
|
||||||
caphrim007
|
caphrim007
|
||||||
cdalbergue
|
cdalbergue
|
||||||
checkphi
|
checkphi
|
||||||
|
chriscroome
|
||||||
chrismeyersfsu
|
chrismeyersfsu
|
||||||
ChristopherGAndrews
|
ChristopherGAndrews
|
||||||
cmodijk
|
cmodijk
|
||||||
|
@ -56,13 +61,14 @@ CormacBracken
|
||||||
cosmix
|
cosmix
|
||||||
cptMikky
|
cptMikky
|
||||||
crashes
|
crashes
|
||||||
|
d-lee
|
||||||
|
d-rupp
|
||||||
dagwieers
|
dagwieers
|
||||||
damianmoore
|
damianmoore
|
||||||
Davidffry
|
Davidffry
|
||||||
denisemauldin
|
denisemauldin
|
||||||
|
dennisurtubia
|
||||||
diclophis
|
diclophis
|
||||||
d-lee
|
|
||||||
d-rupp
|
|
||||||
dmp1ce
|
dmp1ce
|
||||||
dnelson
|
dnelson
|
||||||
dramaley
|
dramaley
|
||||||
|
@ -72,9 +78,11 @@ DSpeichert
|
||||||
dungdm93
|
dungdm93
|
||||||
dwagelaar
|
dwagelaar
|
||||||
dylanjbarth
|
dylanjbarth
|
||||||
einarc
|
|
||||||
E-M
|
E-M
|
||||||
|
einarc
|
||||||
|
elpavel
|
||||||
eowin
|
eowin
|
||||||
|
eRadical
|
||||||
Ernest0x
|
Ernest0x
|
||||||
esamattis
|
esamattis
|
||||||
Everspace
|
Everspace
|
||||||
|
@ -82,24 +90,30 @@ F21
|
||||||
faitno
|
faitno
|
||||||
felixfontein
|
felixfontein
|
||||||
flatrocks
|
flatrocks
|
||||||
|
FlorianPerrot
|
||||||
fourjay
|
fourjay
|
||||||
fraff
|
fraff
|
||||||
|
francescsanjuanmrf
|
||||||
g00fy-
|
g00fy-
|
||||||
geerlingguy
|
geerlingguy
|
||||||
georgeOsdDev
|
georgeOsdDev
|
||||||
ghjm
|
ghjm
|
||||||
ghost
|
ghost
|
||||||
|
GhostLyrics
|
||||||
giacmir
|
giacmir
|
||||||
giorgio-v
|
giorgio-v
|
||||||
gkoller
|
gkoller
|
||||||
|
gotmax23
|
||||||
gottwald
|
gottwald
|
||||||
gstorme
|
gstorme
|
||||||
gundalow
|
gundalow
|
||||||
hansbaer
|
hansbaer
|
||||||
hchargois
|
hchargois
|
||||||
hluaces
|
hluaces
|
||||||
|
hubiongithub
|
||||||
hwali
|
hwali
|
||||||
hyperfocus1338
|
hyperfocus1338
|
||||||
|
IBims1NicerTobi
|
||||||
igormukhingmailcom
|
igormukhingmailcom
|
||||||
imjoseangel
|
imjoseangel
|
||||||
infigoKriti
|
infigoKriti
|
||||||
|
@ -164,8 +178,8 @@ markdorison
|
||||||
markotitel
|
markotitel
|
||||||
marktheunissen
|
marktheunissen
|
||||||
markuman
|
markuman
|
||||||
mattclay
|
|
||||||
matt-horwood-mayden
|
matt-horwood-mayden
|
||||||
|
mattclay
|
||||||
mavimo
|
mavimo
|
||||||
maxamillion
|
maxamillion
|
||||||
maxbube
|
maxbube
|
||||||
|
@ -184,11 +198,15 @@ mkrizek
|
||||||
mmoya
|
mmoya
|
||||||
mohag
|
mohag
|
||||||
mohsenSy
|
mohsenSy
|
||||||
|
moledzki
|
||||||
mpdehaan
|
mpdehaan
|
||||||
|
MRMegaNova
|
||||||
MRwangyd
|
MRwangyd
|
||||||
|
mstinsky
|
||||||
mverwijs
|
mverwijs
|
||||||
mvgrimes
|
mvgrimes
|
||||||
mysqlbox
|
mysqlbox
|
||||||
|
n-cc
|
||||||
netmonk
|
netmonk
|
||||||
nhojpatrick
|
nhojpatrick
|
||||||
nicolas-g
|
nicolas-g
|
||||||
|
@ -202,7 +220,9 @@ organman91
|
||||||
p53
|
p53
|
||||||
pakal
|
pakal
|
||||||
paulbadcock
|
paulbadcock
|
||||||
|
paulcampbell-ayroc
|
||||||
pennycoders
|
pennycoders
|
||||||
|
perlun
|
||||||
petoju
|
petoju
|
||||||
petracvv
|
petracvv
|
||||||
pgrenaud
|
pgrenaud
|
||||||
|
@ -223,12 +243,14 @@ richlv
|
||||||
riupie
|
riupie
|
||||||
rndmh3ro
|
rndmh3ro
|
||||||
robertdebock
|
robertdebock
|
||||||
|
robertsilen
|
||||||
robpblake
|
robpblake
|
||||||
rokka-n
|
rokka-n
|
||||||
Roxyrob
|
Roxyrob
|
||||||
roysmith
|
roysmith
|
||||||
rsicart
|
rsicart
|
||||||
rthouvenin
|
rthouvenin
|
||||||
|
rujschafer
|
||||||
ruudk
|
ruudk
|
||||||
samccann
|
samccann
|
||||||
samdoran
|
samdoran
|
||||||
|
@ -242,6 +264,7 @@ shrikeh
|
||||||
sivel
|
sivel
|
||||||
skalfyfan
|
skalfyfan
|
||||||
skoriy88
|
skoriy88
|
||||||
|
SoledaD208
|
||||||
sperantus
|
sperantus
|
||||||
spoyd
|
spoyd
|
||||||
steverweber
|
steverweber
|
||||||
|
@ -262,19 +285,22 @@ time-palominodb
|
||||||
timorunge
|
timorunge
|
||||||
Tomasthanes
|
Tomasthanes
|
||||||
tomdymond
|
tomdymond
|
||||||
|
tompal3
|
||||||
Tronde
|
Tronde
|
||||||
tuhoanganh
|
tuhoanganh
|
||||||
tvlooy
|
tvlooy
|
||||||
tyll
|
tyll
|
||||||
UncertaintyP
|
UncertaintyP
|
||||||
unnecessary-username
|
unnecessary-username
|
||||||
|
v-zhuravlev
|
||||||
vamshi8
|
vamshi8
|
||||||
vanne
|
vanne
|
||||||
vdboor
|
vdboor
|
||||||
vmahadev
|
vmahadev
|
||||||
v-zhuravlev
|
webknjaz
|
||||||
webmat
|
webmat
|
||||||
wedi
|
wedi
|
||||||
|
wfelipew
|
||||||
whysthatso
|
whysthatso
|
||||||
willthames
|
willthames
|
||||||
windowsansiblernew
|
windowsansiblernew
|
||||||
|
|
23
Makefile
23
Makefile
|
@ -11,6 +11,17 @@ ifdef continue_on_errors
|
||||||
_continue_on_errors = --continue-on-error
|
_continue_on_errors = --continue-on-error
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Set command variables based on database engine
|
||||||
|
# Required for MariaDB 11+ which no longer includes mysql named compatible
|
||||||
|
# executable symlinks
|
||||||
|
ifeq ($(db_engine_name),mysql)
|
||||||
|
_command = mysqld
|
||||||
|
_health_cmd = mysqladmin
|
||||||
|
else
|
||||||
|
_command = mariadbd
|
||||||
|
_health_cmd = mariadb-admin
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: test-integration
|
.PHONY: test-integration
|
||||||
test-integration:
|
test-integration:
|
||||||
@echo -n $(db_engine_name) > tests/integration/db_engine_name
|
@echo -n $(db_engine_name) > tests/integration/db_engine_name
|
||||||
|
@ -29,9 +40,9 @@ test-integration:
|
||||||
--env MYSQL_ROOT_PASSWORD=msandbox \
|
--env MYSQL_ROOT_PASSWORD=msandbox \
|
||||||
--network podman \
|
--network podman \
|
||||||
--publish 3307:3306 \
|
--publish 3307:3306 \
|
||||||
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
||||||
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
||||||
mysqld
|
$(_command)
|
||||||
podman run \
|
podman run \
|
||||||
--detach \
|
--detach \
|
||||||
--replace \
|
--replace \
|
||||||
|
@ -40,9 +51,9 @@ test-integration:
|
||||||
--env MYSQL_ROOT_PASSWORD=msandbox \
|
--env MYSQL_ROOT_PASSWORD=msandbox \
|
||||||
--network podman \
|
--network podman \
|
||||||
--publish 3308:3306 \
|
--publish 3308:3306 \
|
||||||
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
||||||
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
||||||
mysqld
|
$(_command)
|
||||||
podman run \
|
podman run \
|
||||||
--detach \
|
--detach \
|
||||||
--replace \
|
--replace \
|
||||||
|
@ -51,9 +62,9 @@ test-integration:
|
||||||
--env MYSQL_ROOT_PASSWORD=msandbox \
|
--env MYSQL_ROOT_PASSWORD=msandbox \
|
||||||
--network podman \
|
--network podman \
|
||||||
--publish 3309:3306 \
|
--publish 3309:3306 \
|
||||||
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
|
||||||
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
docker.io/library/$(db_engine_name):$(db_engine_version) \
|
||||||
mysqld
|
$(_command)
|
||||||
# Setup replication and restart containers using the same subshell to keep variables alive
|
# Setup replication and restart containers using the same subshell to keep variables alive
|
||||||
db_ver=$(db_engine_version); \
|
db_ver=$(db_engine_version); \
|
||||||
maj="$${db_ver%.*.*}"; \
|
maj="$${db_ver%.*.*}"; \
|
||||||
|
|
|
@ -90,9 +90,9 @@ Here is the table for the support timeline:
|
||||||
|
|
||||||
### ansible-core
|
### ansible-core
|
||||||
|
|
||||||
- stable-2.15
|
|
||||||
- stable-2.16
|
- stable-2.16
|
||||||
- stable-2.17
|
- stable-2.17
|
||||||
|
- stable-2.18
|
||||||
- current development version
|
- current development version
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
|
@ -112,10 +112,10 @@ For MariaDB, only Long Term releases are tested. When multiple LTS are available
|
||||||
- mariadb:10.3.34 (collection version < 3.5.1)
|
- mariadb:10.3.34 (collection version < 3.5.1)
|
||||||
- mariadb:10.4.24 (collection version >= 3.5.2, < 3.10.0)
|
- mariadb:10.4.24 (collection version >= 3.5.2, < 3.10.0)
|
||||||
- mariadb:10.5.18 (collection version >= 3.5.2, < 3.10.0)
|
- mariadb:10.5.18 (collection version >= 3.5.2, < 3.10.0)
|
||||||
- mariadb:10.5.25 (collection version >= 3.10.0)
|
- mariadb:10.5.25 (collection version >= 3.10.0, <3.13.0)
|
||||||
- mariadb:10.6.11 (collection version >= 3.5.2, < 3.10.0)
|
- mariadb:10.6.11 (collection version >= 3.5.2, < 3.10.0)
|
||||||
- mariadb:10.11.8 (collection version >= 3.10.0)
|
- mariadb:10.11.8 (collection version >= 3.10.0)
|
||||||
|
- mariadb:11.4.5 (collection version >= 3.13.0)
|
||||||
|
|
||||||
### Database connectors
|
### Database connectors
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,8 @@ The Makefile accept the following options
|
||||||
- Choices:
|
- Choices:
|
||||||
- "8.0.38" <- mysql
|
- "8.0.38" <- mysql
|
||||||
- "8.4.1" <- mysql (NOT WORKING YET, ansible-test uses Ubuntu 20.04 which is too old to install mysql-community-client 8.4)
|
- "8.4.1" <- mysql (NOT WORKING YET, ansible-test uses Ubuntu 20.04 which is too old to install mysql-community-client 8.4)
|
||||||
- "10.5.25" <- mariadb
|
|
||||||
- "10.11.8" <- mariadb
|
- "10.11.8" <- mariadb
|
||||||
|
- "11.4.5" <- mariadb
|
||||||
- Description: The tag of the container to use for the service containers that will host a primary database and two replicas. Do not use short version, like `mysql:8` (don't do that) because our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. You can use any tag available on [hub.docker.com/_/mysql](https://hub.docker.com/_/mysql) and [hub.docker.com/_/mariadb](https://hub.docker.com/_/mariadb) but GitHub Action will only use the versions listed above.
|
- Description: The tag of the container to use for the service containers that will host a primary database and two replicas. Do not use short version, like `mysql:8` (don't do that) because our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. You can use any tag available on [hub.docker.com/_/mysql](https://hub.docker.com/_/mysql) and [hub.docker.com/_/mariadb](https://hub.docker.com/_/mariadb) but GitHub Action will only use the versions listed above.
|
||||||
|
|
||||||
- `connector_name`
|
- `connector_name`
|
||||||
|
@ -121,7 +121,7 @@ make ansible="stable-2.16" db_engine_name="mysql" db_engine_version="8.0.31" con
|
||||||
make ansible="stable-2.17" db_engine_name="mysql" db_engine_version="8.0.31" connector_name="mysqlclient" connector_version="2.0.3" target="test_mysql_query" keep_containers_alive=1 continue_on_errors=1
|
make ansible="stable-2.17" db_engine_name="mysql" db_engine_version="8.0.31" connector_name="mysqlclient" connector_version="2.0.3" target="test_mysql_query" keep_containers_alive=1 continue_on_errors=1
|
||||||
|
|
||||||
# If your system has an usupported version of Python:
|
# If your system has an usupported version of Python:
|
||||||
make local_python_version="3.10" ansible="stable-2.17" db_engine_name="mariadb" db_engine_version="10.6.11" connector_name="pymysql" connector_version="1.0.2"
|
make local_python_version="3.10" ansible="stable-2.17" db_engine_name="mariadb" db_engine_version="11.4.5" connector_name="pymysql" connector_version="1.0.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -99,13 +99,6 @@ releases:
|
||||||
release_date: '2022-04-26'
|
release_date: '2022-04-26'
|
||||||
3.10.0:
|
3.10.0:
|
||||||
changes:
|
changes:
|
||||||
breaking_changes:
|
|
||||||
- collection - support of mysqlclient connector is deprecated - use PyMySQL
|
|
||||||
connector instead! We will stop testing against it in collection version 4.0.0
|
|
||||||
and remove the related code in 5.0.0 (https://github.com/ansible-collections/community.mysql/issues/654).
|
|
||||||
- mysql_info - The ``users_info`` filter returned variable ``plugin_auth_string``
|
|
||||||
contains the hashed password and it's misleading, it will be removed from
|
|
||||||
community.mysql 4.0.0. Use the `plugin_hash_string` return value instead (https://github.com/ansible-collections/community.mysql/pull/629).
|
|
||||||
bugfixes:
|
bugfixes:
|
||||||
- mysql_info - Add ``plugin_hash_string`` to ``users_info`` filter's output.
|
- mysql_info - Add ``plugin_hash_string`` to ``users_info`` filter's output.
|
||||||
The existing ``plugin_auth_string`` contained the hashed password and thus
|
The existing ``plugin_auth_string`` contained the hashed password and thus
|
||||||
|
@ -122,6 +115,13 @@ releases:
|
||||||
avoid versions 3.8.0 to 3.9.0 (https://github.com/ansible-collections/community.mysql/pull/642).
|
avoid versions 3.8.0 to 3.9.0 (https://github.com/ansible-collections/community.mysql/pull/642).
|
||||||
- mysql_user - add correct ``ed25519`` auth plugin handling (https://github.com/ansible-collections/community.mysql/issues/6).
|
- mysql_user - add correct ``ed25519`` auth plugin handling (https://github.com/ansible-collections/community.mysql/issues/6).
|
||||||
- mysql_variables - fix the module always changes on boolean values (https://github.com/ansible-collections/community.mysql/issues/652).
|
- mysql_variables - fix the module always changes on boolean values (https://github.com/ansible-collections/community.mysql/issues/652).
|
||||||
|
deprecated_features:
|
||||||
|
- collection - support of mysqlclient connector is deprecated - use PyMySQL
|
||||||
|
connector instead! We will stop testing against it in collection version 4.0.0
|
||||||
|
and remove the related code in 5.0.0 (https://github.com/ansible-collections/community.mysql/issues/654).
|
||||||
|
- mysql_info - The ``users_info`` filter returned variable ``plugin_auth_string``
|
||||||
|
contains the hashed password and it's misleading, it will be removed from
|
||||||
|
community.mysql 4.0.0. Use the `plugin_hash_string` return value instead (https://github.com/ansible-collections/community.mysql/pull/629).
|
||||||
minor_changes:
|
minor_changes:
|
||||||
- mysql_info - Add ``tls_requires`` returned value for the ``users_info`` filter
|
- mysql_info - Add ``tls_requires`` returned value for the ``users_info`` filter
|
||||||
(https://github.com/ansible-collections/community.mysql/pull/628).
|
(https://github.com/ansible-collections/community.mysql/pull/628).
|
||||||
|
@ -158,13 +158,13 @@ releases:
|
||||||
release_date: '2024-08-22'
|
release_date: '2024-08-22'
|
||||||
3.10.1:
|
3.10.1:
|
||||||
changes:
|
changes:
|
||||||
breaking_changes:
|
|
||||||
- mysql_user - the ``user`` alias of the ``name`` argument has been deprecated
|
|
||||||
and will be removed in collection version 5.0.0. Use the ``name`` argument
|
|
||||||
instead.
|
|
||||||
bugfixes:
|
bugfixes:
|
||||||
- mysql_user - module makes changes when is executed with ``plugin_auth_string``
|
- mysql_user - module makes changes when is executed with ``plugin_auth_string``
|
||||||
parameter and check mode.
|
parameter and check mode.
|
||||||
|
deprecated_features:
|
||||||
|
- mysql_user - the ``user`` alias of the ``name`` argument has been deprecated
|
||||||
|
and will be removed in collection version 5.0.0. Use the ``name`` argument
|
||||||
|
instead.
|
||||||
release_summary: 'This is a patch release of the ``community.mysql`` collection.
|
release_summary: 'This is a patch release of the ``community.mysql`` collection.
|
||||||
|
|
||||||
Besides a bugfix, it contains an important upcoming breaking-change information.'
|
Besides a bugfix, it contains an important upcoming breaking-change information.'
|
||||||
|
@ -201,6 +201,99 @@ releases:
|
||||||
- 0-mysql_user.yml
|
- 0-mysql_user.yml
|
||||||
- 3.10.3.yml
|
- 3.10.3.yml
|
||||||
release_date: '2024-09-09'
|
release_date: '2024-09-09'
|
||||||
|
3.11.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- mysql_user,mysql_role - The sql_mode ANSI_QUOTES affects how the modules mysql_user
|
||||||
|
and mysql_role compare the existing privileges with the configured privileges,
|
||||||
|
as well as decide whether double quotes or backticks should be used in the
|
||||||
|
GRANT statements. Pointing out in issue 671, the modules mysql_user and mysql_role
|
||||||
|
allow users to enable/disable ANSI_QUOTES in session variable (within a DB
|
||||||
|
session, the session variable always overwrites the global one). But due to
|
||||||
|
the issue, the modules do not check for ANSI_MODE in the session variable,
|
||||||
|
instead, they only check in the GLOBAL one.That behavior is not only limiting
|
||||||
|
the users' flexibility, but also not allowing users to explicitly disable
|
||||||
|
ANSI_MODE to work around such bugs like https://bugs.mysql.com/bug.php?id=115953.
|
||||||
|
(https://github.com/ansible-collections/community.mysql/issues/671)
|
||||||
|
minor_changes:
|
||||||
|
- mysql_info - adds the count of tables for each database to the returned values.
|
||||||
|
It is possible to exclude this new field using the ``db_table_count`` exclusion
|
||||||
|
filter. (https://github.com/ansible-collections/community.mysql/pull/691)
|
||||||
|
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.'
|
||||||
|
fragments:
|
||||||
|
- 3.11.0.yml
|
||||||
|
- 591-mysql_info-db_tables_count.yml
|
||||||
|
- 671-modules_util_user.yml
|
||||||
|
release_date: '2024-11-19'
|
||||||
|
3.12.0:
|
||||||
|
changes:
|
||||||
|
minor_changes:
|
||||||
|
- mysql_db - added ``zstd`` (de)compression support for ``import``/``dump``
|
||||||
|
states (https://github.com/ansible-collections/community.mysql/issues/696).
|
||||||
|
- mysql_query - returns the ``execution_time_ms`` list containing execution
|
||||||
|
time per query in milliseconds.
|
||||||
|
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.'
|
||||||
|
fragments:
|
||||||
|
- 0-mysql_query-returns-exec-time-ms.yml
|
||||||
|
- 3.12.0.yml
|
||||||
|
- 696-mysql-db-add-zstd-support.yml
|
||||||
|
release_date: '2025-01-17'
|
||||||
|
3.13.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- mysql_db - fix dump and import to find MariaDB binaries (mariadb and mariadb-dump)
|
||||||
|
when MariaDB 11+ is used and symbolic links to MySQL binaries are absent.
|
||||||
|
minor_changes:
|
||||||
|
- Integration tests for MariaDB 11.4 have replaced those for 10.5. The previous
|
||||||
|
version is now 10.11.
|
||||||
|
- mysql_user - add ``locked`` option to lock/unlock users, this is mainly used
|
||||||
|
to have users that will act as definers on stored procedures.
|
||||||
|
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.'
|
||||||
|
fragments:
|
||||||
|
- 3.13.0.yml
|
||||||
|
- 702-user_locking.yaml
|
||||||
|
- tests_mariadb_11_4.yml
|
||||||
|
release_date: '2025-03-21'
|
||||||
|
3.14.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- mysql_info - fix a crash (ERROR 1141, There is no such grant defined for user
|
||||||
|
'PUBLIC' on host '%') when using the ``users_info`` filter with a PUBLIC role
|
||||||
|
present in MariaDB 10.11+. Do note that the fix doesn't change the fact that
|
||||||
|
the module won't return the privileges from the PUBLIC role in the users privileges
|
||||||
|
list. It can't do that because you have to login as the particular user and
|
||||||
|
use `SHOW GRANTS FOR CURRENT_USER`. We considered using an aggregation with
|
||||||
|
the `SHOW GRANTS FOR PUBLIC` command. However, this approach would make copying
|
||||||
|
users from one server to another transform the privileges inherited from the
|
||||||
|
role as if they were direct privileges on the user.
|
||||||
|
- mysql_replication - fixed an issue where setting ``primary_ssl_verify_server_cert``
|
||||||
|
to false had no effect (https://github.com/ansible-collections/community.mysql/issues/689).
|
||||||
|
minor_changes:
|
||||||
|
- mysql_replication - change default value for ``primary_ssl_verify_server_cert``
|
||||||
|
from False to None. This should not affect existing playbooks (https://github.com/ansible-collections/community.mysql/pull/707).
|
||||||
|
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.'''
|
||||||
|
fragments:
|
||||||
|
- 707-source_ssl_verify_server_cert.yml
|
||||||
|
- grant_to_public.yml
|
||||||
|
- release_3_14_0.yml
|
||||||
|
release_date: '2025-05-23'
|
||||||
3.2.0:
|
3.2.0:
|
||||||
changes:
|
changes:
|
||||||
bugfixes:
|
bugfixes:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
namespace: community
|
namespace: community
|
||||||
name: mysql
|
name: mysql
|
||||||
version: 3.10.3
|
version: 3.14.1
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Ansible community
|
- Ansible community
|
||||||
|
|
|
@ -1,2 +1,11 @@
|
||||||
---
|
---
|
||||||
requires_ansible: '>=2.9.10'
|
requires_ansible: '>=2.9.10'
|
||||||
|
action_groups:
|
||||||
|
all:
|
||||||
|
- mysql_db
|
||||||
|
- mysql_info
|
||||||
|
- mysql_query
|
||||||
|
- mysql_replication
|
||||||
|
- mysql_role
|
||||||
|
- mysql_user
|
||||||
|
- mysql_variables
|
||||||
|
|
|
@ -32,7 +32,7 @@ class InvalidPrivsError(Exception):
|
||||||
|
|
||||||
|
|
||||||
def get_mode(cursor):
|
def get_mode(cursor):
|
||||||
cursor.execute('SELECT @@GLOBAL.sql_mode')
|
cursor.execute('SELECT @@sql_mode')
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
mode_str = result[0]
|
mode_str = result[0]
|
||||||
if 'ANSI' in mode_str:
|
if 'ANSI' in mode_str:
|
||||||
|
@ -52,6 +52,25 @@ def user_exists(cursor, user, host, host_all):
|
||||||
return count[0] > 0
|
return count[0] > 0
|
||||||
|
|
||||||
|
|
||||||
|
def user_is_locked(cursor, user, host):
|
||||||
|
cursor.execute("SHOW CREATE USER %s@%s", (user, host))
|
||||||
|
|
||||||
|
# Per discussions on irc:libera.chat:#maria the query may return up to 2 rows but "ACCOUNT LOCK" should always be in the first row.
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
|
# ACCOUNT LOCK does not have to be the last option in the CREATE USER query.
|
||||||
|
# Need to handle both DictCursor and non-DictCursor
|
||||||
|
if isinstance(result, tuple):
|
||||||
|
if result[0].find('ACCOUNT LOCK') > 0:
|
||||||
|
return True
|
||||||
|
elif isinstance(result, dict):
|
||||||
|
for res in result.values():
|
||||||
|
if res.find('ACCOUNT LOCK') > 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def sanitize_requires(tls_requires):
|
def sanitize_requires(tls_requires):
|
||||||
sanitized_requires = {}
|
sanitized_requires = {}
|
||||||
if tls_requires:
|
if tls_requires:
|
||||||
|
@ -160,7 +179,7 @@ def get_existing_authentication(cursor, user, host=None):
|
||||||
def user_add(cursor, user, host, host_all, password, encrypted,
|
def user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, salt, new_priv,
|
plugin, plugin_hash_string, plugin_auth_string, salt, new_priv,
|
||||||
attributes, tls_requires, reuse_existing_password, module,
|
attributes, tls_requires, reuse_existing_password, module,
|
||||||
password_expire, password_expire_interval):
|
password_expire, password_expire_interval, locked=False):
|
||||||
# If attributes are set, perform a sanity check to ensure server supports user attributes before creating user
|
# If attributes are set, perform a sanity check to ensure server supports user attributes before creating user
|
||||||
if attributes and not get_attribute_support(cursor):
|
if attributes and not get_attribute_support(cursor):
|
||||||
module.fail_json(msg="user attributes were specified but the server does not support user attributes")
|
module.fail_json(msg="user attributes were specified but the server does not support user attributes")
|
||||||
|
@ -250,6 +269,9 @@ def user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
cursor.execute("ALTER USER %s@%s ATTRIBUTE %s", (user, host, json.dumps(attributes)))
|
cursor.execute("ALTER USER %s@%s ATTRIBUTE %s", (user, host, json.dumps(attributes)))
|
||||||
final_attributes = attributes_get(cursor, user, host)
|
final_attributes = attributes_get(cursor, user, host)
|
||||||
|
|
||||||
|
if locked:
|
||||||
|
cursor.execute("ALTER USER %s@%s ACCOUNT LOCK", (user, host))
|
||||||
|
|
||||||
return {'changed': True, 'password_changed': not used_existing_password, 'attributes': final_attributes}
|
return {'changed': True, 'password_changed': not used_existing_password, 'attributes': final_attributes}
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,7 +286,7 @@ def is_hash(password):
|
||||||
def user_mod(cursor, user, host, host_all, password, encrypted,
|
def user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, salt, new_priv,
|
plugin, plugin_hash_string, plugin_auth_string, salt, new_priv,
|
||||||
append_privs, subtract_privs, attributes, tls_requires, module,
|
append_privs, subtract_privs, attributes, tls_requires, module,
|
||||||
password_expire, password_expire_interval, role=False, maria_role=False):
|
password_expire, password_expire_interval, locked=None, role=False, maria_role=False):
|
||||||
changed = False
|
changed = False
|
||||||
msg = "User unchanged"
|
msg = "User unchanged"
|
||||||
grant_option = False
|
grant_option = False
|
||||||
|
@ -536,6 +558,22 @@ def user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
if attribute_support:
|
if attribute_support:
|
||||||
final_attributes = attributes_get(cursor, user, host)
|
final_attributes = attributes_get(cursor, user, host)
|
||||||
|
|
||||||
|
if not role and locked is not None and user_is_locked(cursor, user, host) != locked:
|
||||||
|
if not module.check_mode:
|
||||||
|
if locked:
|
||||||
|
cursor.execute("ALTER USER %s@%s ACCOUNT LOCK", (user, host))
|
||||||
|
msg = 'User locked'
|
||||||
|
else:
|
||||||
|
cursor.execute("ALTER USER %s@%s ACCOUNT UNLOCK", (user, host))
|
||||||
|
msg = 'User unlocked'
|
||||||
|
else:
|
||||||
|
if locked:
|
||||||
|
msg = 'User will be locked'
|
||||||
|
else:
|
||||||
|
msg = 'User will be unlocked'
|
||||||
|
|
||||||
|
changed = True
|
||||||
|
|
||||||
if role:
|
if role:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -624,7 +662,7 @@ def privileges_get(cursor, user, host, maria_role=False):
|
||||||
if not maria_role:
|
if not maria_role:
|
||||||
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0])
|
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3@(['`"]).*\\4( IDENTIFIED BY PASSWORD (['`"]).+\\6)? ?(.*)""", grant[0])
|
||||||
else:
|
else:
|
||||||
res = re.match("""GRANT (.+) ON (.+) TO (['`"]).*\\3""", grant[0])
|
res = re.match("""GRANT (.+) ON (.+) TO .*""", grant[0])
|
||||||
|
|
||||||
if res is None:
|
if res is None:
|
||||||
# If a user has roles assigned, we'll have one of priv tuples looking like
|
# If a user has roles assigned, we'll have one of priv tuples looking like
|
||||||
|
|
|
@ -46,8 +46,8 @@ options:
|
||||||
target:
|
target:
|
||||||
description:
|
description:
|
||||||
- Location, on the remote host, of the dump file to read from or write to.
|
- Location, on the remote host, of the dump file to read from or write to.
|
||||||
- Uncompressed SQL files (C(.sql)) as well as bzip2 (C(.bz2)), gzip (C(.gz)) and
|
- Uncompressed SQL files (C(.sql)) as well as bzip2 (C(.bz2)), gzip (C(.gz)),
|
||||||
xz (Added in 2.0) compressed files are supported.
|
xz (Added in 2.0) and zstd (C(.zst)) (Added in 3.12.0) compressed files are supported.
|
||||||
type: path
|
type: path
|
||||||
single_transaction:
|
single_transaction:
|
||||||
description:
|
description:
|
||||||
|
@ -159,7 +159,7 @@ options:
|
||||||
pipefail:
|
pipefail:
|
||||||
description:
|
description:
|
||||||
- Use C(bash) instead of C(sh) and add C(-o pipefail) to catch errors from the
|
- Use C(bash) instead of C(sh) and add C(-o pipefail) to catch errors from the
|
||||||
mysql_dump command when I(state=import) and compression is used.
|
mysql_dump command when I(state=dump) and compression is used.
|
||||||
- The default is C(no) to prevent issues on systems without bash as a default interpreter.
|
- The default is C(no) to prevent issues on systems without bash as a default interpreter.
|
||||||
- The default will change to C(yes) in community.mysql 4.0.0.
|
- The default will change to C(yes) in community.mysql 4.0.0.
|
||||||
type: bool
|
type: bool
|
||||||
|
@ -386,67 +386,75 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port,
|
||||||
encoding=None, force=False, master_data=0, skip_lock_tables=False,
|
encoding=None, force=False, master_data=0, skip_lock_tables=False,
|
||||||
dump_extra_args=None, unsafe_password=False, restrict_config_file=False,
|
dump_extra_args=None, unsafe_password=False, restrict_config_file=False,
|
||||||
check_implicit_admin=False, pipefail=False):
|
check_implicit_admin=False, pipefail=False):
|
||||||
cmd = module.get_bin_path('mysqldump', True)
|
|
||||||
|
cmd_str = 'mysqldump'
|
||||||
|
if server_implementation == 'mariadb' and LooseVersion(server_version) >= LooseVersion("10.4.6"):
|
||||||
|
cmd_str = 'mariadb-dump'
|
||||||
|
try:
|
||||||
|
cmd = [module.get_bin_path(cmd_str, True)]
|
||||||
|
except Exception as e:
|
||||||
|
return 1, "", "Error determining dump command: %s" % str(e)
|
||||||
|
|
||||||
# If defined, mysqldump demands --defaults-extra-file be the first option
|
# If defined, mysqldump demands --defaults-extra-file be the first option
|
||||||
if config_file:
|
if config_file:
|
||||||
if restrict_config_file:
|
if restrict_config_file:
|
||||||
cmd += " --defaults-file=%s" % shlex_quote(config_file)
|
cmd.append("--defaults-file=%s" % shlex_quote(config_file))
|
||||||
else:
|
else:
|
||||||
cmd += " --defaults-extra-file=%s" % shlex_quote(config_file)
|
cmd.append("--defaults-extra-file=%s" % shlex_quote(config_file))
|
||||||
|
|
||||||
if check_implicit_admin:
|
if check_implicit_admin:
|
||||||
cmd += " --user=root --password=''"
|
cmd.append("--user=root --password=''")
|
||||||
else:
|
else:
|
||||||
if user is not None:
|
if user is not None:
|
||||||
cmd += " --user=%s" % shlex_quote(user)
|
cmd.append("--user=%s" % shlex_quote(user))
|
||||||
|
|
||||||
if password is not None:
|
if password is not None:
|
||||||
if not unsafe_password:
|
if not unsafe_password:
|
||||||
cmd += " --password=%s" % shlex_quote(password)
|
cmd.append("--password=%s" % shlex_quote(password))
|
||||||
else:
|
else:
|
||||||
cmd += " --password=%s" % password
|
cmd.append("--password=%s" % password)
|
||||||
|
|
||||||
if ssl_cert is not None:
|
if ssl_cert is not None:
|
||||||
cmd += " --ssl-cert=%s" % shlex_quote(ssl_cert)
|
cmd.append("--ssl-cert=%s" % shlex_quote(ssl_cert))
|
||||||
if ssl_key is not None:
|
if ssl_key is not None:
|
||||||
cmd += " --ssl-key=%s" % shlex_quote(ssl_key)
|
cmd.append("--ssl-key=%s" % shlex_quote(ssl_key))
|
||||||
if ssl_ca is not None:
|
if ssl_ca is not None:
|
||||||
cmd += " --ssl-ca=%s" % shlex_quote(ssl_ca)
|
cmd.append("--ssl-ca=%s" % shlex_quote(ssl_ca))
|
||||||
if force:
|
if force:
|
||||||
cmd += " --force"
|
cmd.append("--force")
|
||||||
if socket is not None:
|
if socket is not None:
|
||||||
cmd += " --socket=%s" % shlex_quote(socket)
|
cmd.append("--socket=%s" % shlex_quote(socket))
|
||||||
else:
|
else:
|
||||||
cmd += " --host=%s --port=%i" % (shlex_quote(host), port)
|
cmd.append("--host=%s --port=%i" % (shlex_quote(host), port))
|
||||||
|
|
||||||
if all_databases:
|
if all_databases:
|
||||||
cmd += " --all-databases"
|
cmd.append("--all-databases")
|
||||||
elif len(db_name) > 1:
|
elif len(db_name) > 1:
|
||||||
cmd += " --databases {0}".format(' '.join(db_name))
|
cmd.append("--databases {0}".format(' '.join(db_name)))
|
||||||
else:
|
else:
|
||||||
cmd += " %s" % shlex_quote(' '.join(db_name))
|
cmd.append("%s" % shlex_quote(' '.join(db_name)))
|
||||||
|
|
||||||
if skip_lock_tables:
|
if skip_lock_tables:
|
||||||
cmd += " --skip-lock-tables"
|
cmd.append("--skip-lock-tables")
|
||||||
if (encoding is not None) and (encoding != ""):
|
if (encoding is not None) and (encoding != ""):
|
||||||
cmd += " --default-character-set=%s" % shlex_quote(encoding)
|
cmd.append("--default-character-set=%s" % shlex_quote(encoding))
|
||||||
if single_transaction:
|
if single_transaction:
|
||||||
cmd += " --single-transaction=true"
|
cmd.append("--single-transaction=true")
|
||||||
if quick:
|
if quick:
|
||||||
cmd += " --quick"
|
cmd.append("--quick")
|
||||||
if ignore_tables:
|
if ignore_tables:
|
||||||
for an_ignored_table in ignore_tables:
|
for an_ignored_table in ignore_tables:
|
||||||
cmd += " --ignore-table={0}".format(an_ignored_table)
|
cmd.append("--ignore-table={0}".format(an_ignored_table))
|
||||||
if hex_blob:
|
if hex_blob:
|
||||||
cmd += " --hex-blob"
|
cmd.append("--hex-blob")
|
||||||
if master_data:
|
if master_data:
|
||||||
if (server_implementation == 'mysql' and
|
if (server_implementation == 'mysql' and
|
||||||
LooseVersion(server_version) >= LooseVersion("8.2.0")):
|
LooseVersion(server_version) >= LooseVersion("8.2.0")):
|
||||||
cmd += " --source-data=%s" % master_data
|
cmd.append("--source-data=%s" % master_data)
|
||||||
else:
|
else:
|
||||||
cmd += " --master-data=%s" % master_data
|
cmd.append("--master-data=%s" % master_data)
|
||||||
if dump_extra_args is not None:
|
if dump_extra_args is not None:
|
||||||
cmd += " " + dump_extra_args
|
cmd.append(dump_extra_args)
|
||||||
|
|
||||||
path = None
|
path = None
|
||||||
if os.path.splitext(target)[-1] == '.gz':
|
if os.path.splitext(target)[-1] == '.gz':
|
||||||
|
@ -455,6 +463,10 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port,
|
||||||
path = module.get_bin_path('bzip2', True)
|
path = module.get_bin_path('bzip2', True)
|
||||||
elif os.path.splitext(target)[-1] == '.xz':
|
elif os.path.splitext(target)[-1] == '.xz':
|
||||||
path = module.get_bin_path('xz', True)
|
path = module.get_bin_path('xz', True)
|
||||||
|
elif os.path.splitext(target)[-1] == '.zst':
|
||||||
|
path = module.get_bin_path('zstd', True)
|
||||||
|
|
||||||
|
cmd = ' '.join(cmd)
|
||||||
|
|
||||||
if path:
|
if path:
|
||||||
cmd = '%s | %s > %s' % (cmd, path, shlex_quote(target))
|
cmd = '%s | %s > %s' % (cmd, path, shlex_quote(target))
|
||||||
|
@ -474,13 +486,21 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port,
|
||||||
|
|
||||||
|
|
||||||
def db_import(module, host, user, password, db_name, target, all_databases, port, config_file,
|
def db_import(module, host, user, password, db_name, target, all_databases, port, config_file,
|
||||||
socket=None, ssl_cert=None, ssl_key=None, ssl_ca=None, encoding=None, force=False,
|
server_implementation, server_version, socket=None, ssl_cert=None, ssl_key=None, ssl_ca=None,
|
||||||
|
encoding=None, force=False,
|
||||||
use_shell=False, unsafe_password=False, restrict_config_file=False,
|
use_shell=False, unsafe_password=False, restrict_config_file=False,
|
||||||
check_implicit_admin=False):
|
check_implicit_admin=False):
|
||||||
if not os.path.exists(target):
|
if not os.path.exists(target):
|
||||||
return module.fail_json(msg="target %s does not exist on the host" % target)
|
return module.fail_json(msg="target %s does not exist on the host" % target)
|
||||||
|
|
||||||
cmd = [module.get_bin_path('mysql', True)]
|
cmd_str = 'mysql'
|
||||||
|
if server_implementation == 'mariadb' and LooseVersion(server_version) >= LooseVersion("10.4.6"):
|
||||||
|
cmd_str = 'mariadb'
|
||||||
|
try:
|
||||||
|
cmd = [module.get_bin_path(cmd_str, True)]
|
||||||
|
except Exception as e:
|
||||||
|
return 1, "", "Error determining mysql/mariadb command: %s" % str(e)
|
||||||
|
|
||||||
# --defaults-file must go first, or errors out
|
# --defaults-file must go first, or errors out
|
||||||
if config_file:
|
if config_file:
|
||||||
if restrict_config_file:
|
if restrict_config_file:
|
||||||
|
@ -526,6 +546,8 @@ def db_import(module, host, user, password, db_name, target, all_databases, port
|
||||||
comp_prog_path = module.get_bin_path('bzip2', required=True)
|
comp_prog_path = module.get_bin_path('bzip2', required=True)
|
||||||
elif os.path.splitext(target)[-1] == '.xz':
|
elif os.path.splitext(target)[-1] == '.xz':
|
||||||
comp_prog_path = module.get_bin_path('xz', required=True)
|
comp_prog_path = module.get_bin_path('xz', required=True)
|
||||||
|
elif os.path.splitext(target)[-1] == '.zst':
|
||||||
|
comp_prog_path = module.get_bin_path('zstd', required=True)
|
||||||
if comp_prog_path:
|
if comp_prog_path:
|
||||||
# The line below is for returned data only:
|
# The line below is for returned data only:
|
||||||
executed_commands.append('%s -dc %s | %s' % (comp_prog_path, target, cmd))
|
executed_commands.append('%s -dc %s | %s' % (comp_prog_path, target, cmd))
|
||||||
|
@ -768,8 +790,8 @@ def main():
|
||||||
rc, stdout, stderr = db_import(module, login_host, login_user,
|
rc, stdout, stderr = db_import(module, login_host, login_user,
|
||||||
login_password, db, target,
|
login_password, db, target,
|
||||||
all_databases,
|
all_databases,
|
||||||
login_port, config_file,
|
login_port, config_file, server_implementation,
|
||||||
socket, ssl_cert, ssl_key, ssl_ca,
|
server_version, socket, ssl_cert, ssl_key, ssl_ca,
|
||||||
encoding, force, use_shell, unsafe_login_password,
|
encoding, force, use_shell, unsafe_login_password,
|
||||||
restrict_config_file, check_implicit_admin)
|
restrict_config_file, check_implicit_admin)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
@ -35,7 +36,7 @@ options:
|
||||||
exclude_fields:
|
exclude_fields:
|
||||||
description:
|
description:
|
||||||
- List of fields which are not needed to collect.
|
- List of fields which are not needed to collect.
|
||||||
- "Supports elements: C(db_size). Unsupported elements will be ignored."
|
- "Supports elements: C(db_size), C(db_table_count). Unsupported elements will be ignored."
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: '0.1.0'
|
version_added: '0.1.0'
|
||||||
|
@ -49,6 +50,7 @@ notes:
|
||||||
- Compatible with MariaDB or MySQL.
|
- Compatible with MariaDB or MySQL.
|
||||||
- Calculating the size of a database might be slow, depending on the number and size of tables in it.
|
- Calculating the size of a database might be slow, depending on the number and size of tables in it.
|
||||||
To avoid this, use I(exclude_fields=db_size).
|
To avoid this, use I(exclude_fields=db_size).
|
||||||
|
- filters C(users_info) doesn't support MariaDB roles.
|
||||||
|
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
|
@ -150,6 +152,7 @@ EXAMPLES = r'''
|
||||||
tls_requires: "{{ item.tls_requires | default(omit) }}"
|
tls_requires: "{{ item.tls_requires | default(omit) }}"
|
||||||
priv: "{{ item.priv | default(omit) }}"
|
priv: "{{ item.priv | default(omit) }}"
|
||||||
resource_limits: "{{ item.resource_limits | default(omit) }}"
|
resource_limits: "{{ item.resource_limits | default(omit) }}"
|
||||||
|
locked: "{{ item.locked | default(omit) }}"
|
||||||
column_case_sensitive: true
|
column_case_sensitive: true
|
||||||
state: present
|
state: present
|
||||||
loop: "{{ result.users_info }}"
|
loop: "{{ result.users_info }}"
|
||||||
|
@ -159,6 +162,7 @@ EXAMPLES = r'''
|
||||||
- item.name != 'root' # In case you don't want to import admin accounts
|
- item.name != 'root' # In case you don't want to import admin accounts
|
||||||
- item.name != 'mariadb.sys'
|
- item.name != 'mariadb.sys'
|
||||||
- item.name != 'mysql'
|
- item.name != 'mysql'
|
||||||
|
- item.name != 'PUBLIC' # MariaDB roles are not supported
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
|
@ -204,13 +208,19 @@ databases:
|
||||||
returned: if not excluded by filter
|
returned: if not excluded by filter
|
||||||
type: dict
|
type: dict
|
||||||
sample:
|
sample:
|
||||||
- { "mysql": { "size": 656594 }, "information_schema": { "size": 73728 } }
|
- { "mysql": { "size": 656594, "tables": 31 }, "information_schema": { "size": 73728, "tables": 79 } }
|
||||||
contains:
|
contains:
|
||||||
size:
|
size:
|
||||||
description: Database size in bytes.
|
description: Database size in bytes.
|
||||||
returned: if not excluded by filter
|
returned: if not excluded by filter
|
||||||
type: dict
|
type: dict
|
||||||
sample: { 'size': 656594 }
|
sample: { 'size': 656594 }
|
||||||
|
tables:
|
||||||
|
description: Count of tables and views in that database.
|
||||||
|
returned: if not excluded by filter
|
||||||
|
type: dict
|
||||||
|
sample: { 'tables': 12 }
|
||||||
|
version_added: '3.11.0'
|
||||||
settings:
|
settings:
|
||||||
description: Global settings (variables) information.
|
description: Global settings (variables) information.
|
||||||
returned: if not excluded by filter
|
returned: if not excluded by filter
|
||||||
|
@ -239,6 +249,7 @@ users_info:
|
||||||
If the output is fed to M(community.mysql.mysql_user), the
|
If the output is fed to M(community.mysql.mysql_user), the
|
||||||
``plugin_auth_string`` will most likely be unreadable due to non-binary
|
``plugin_auth_string`` will most likely be unreadable due to non-binary
|
||||||
characters.
|
characters.
|
||||||
|
- The "locked" field was aded in ``community.mysql`` 3.13.
|
||||||
returned: if not excluded by filter
|
returned: if not excluded by filter
|
||||||
type: dict
|
type: dict
|
||||||
sample:
|
sample:
|
||||||
|
@ -248,7 +259,8 @@ users_info:
|
||||||
"plugin": "mysql_native_password",
|
"plugin": "mysql_native_password",
|
||||||
"priv": "db1.*:SELECT/db2.*:SELECT",
|
"priv": "db1.*:SELECT/db2.*:SELECT",
|
||||||
"resource_limits": { "MAX_USER_CONNECTIONS": 100 },
|
"resource_limits": { "MAX_USER_CONNECTIONS": 100 },
|
||||||
"tls_requires": { "SSL": null } }
|
"tls_requires": { "SSL": null },
|
||||||
|
"locked": false }
|
||||||
version_added: '3.8.0'
|
version_added: '3.8.0'
|
||||||
engines:
|
engines:
|
||||||
description: Information about the server's storage engines.
|
description: Information about the server's storage engines.
|
||||||
|
@ -312,6 +324,7 @@ from ansible_collections.community.mysql.plugins.module_utils.user import (
|
||||||
get_resource_limits,
|
get_resource_limits,
|
||||||
get_existing_authentication,
|
get_existing_authentication,
|
||||||
get_user_implementation,
|
get_user_implementation,
|
||||||
|
user_is_locked,
|
||||||
)
|
)
|
||||||
from ansible.module_utils.six import iteritems
|
from ansible.module_utils.six import iteritems
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
@ -595,7 +608,9 @@ class MySQL_Info(object):
|
||||||
user = line['User']
|
user = line['User']
|
||||||
host = line['Host']
|
host = line['Host']
|
||||||
|
|
||||||
user_priv = privileges_get(self.cursor, user, host)
|
# MariaDB roles have no host
|
||||||
|
is_role = self.server_implementation == 'mariadb' and not host
|
||||||
|
user_priv = privileges_get(self.cursor, user, host, maria_role=is_role)
|
||||||
|
|
||||||
if not user_priv:
|
if not user_priv:
|
||||||
self.module.warn("No privileges found for %s on host %s" % (user, host))
|
self.module.warn("No privileges found for %s on host %s" % (user, host))
|
||||||
|
@ -646,8 +661,10 @@ class MySQL_Info(object):
|
||||||
if authentications:
|
if authentications:
|
||||||
output_dict.update(authentications[0])
|
output_dict.update(authentications[0])
|
||||||
|
|
||||||
|
if line.get('is_role') and line['is_role'] == 'N':
|
||||||
|
output_dict['locked'] = user_is_locked(self.cursor, user, host)
|
||||||
|
|
||||||
# TODO password_option
|
# TODO password_option
|
||||||
# TODO lock_option
|
|
||||||
# but both are not supported by mysql_user atm. So no point yet.
|
# but both are not supported by mysql_user atm. So no point yet.
|
||||||
|
|
||||||
output.append(output_dict)
|
output.append(output_dict)
|
||||||
|
@ -656,40 +673,39 @@ class MySQL_Info(object):
|
||||||
|
|
||||||
def __get_databases(self, exclude_fields, return_empty_dbs):
|
def __get_databases(self, exclude_fields, return_empty_dbs):
|
||||||
"""Get info about databases."""
|
"""Get info about databases."""
|
||||||
if not exclude_fields:
|
|
||||||
query = ('SELECT table_schema AS "name", '
|
|
||||||
'SUM(data_length + index_length) AS "size" '
|
|
||||||
'FROM information_schema.TABLES GROUP BY table_schema')
|
|
||||||
else:
|
|
||||||
if 'db_size' in exclude_fields:
|
|
||||||
query = ('SELECT table_schema AS "name" '
|
|
||||||
'FROM information_schema.TABLES GROUP BY table_schema')
|
|
||||||
|
|
||||||
res = self.__exec_sql(query)
|
def is_field_included(field_name):
|
||||||
|
return not exclude_fields or 'db_{}'.format(field_name) not in exclude_fields
|
||||||
|
|
||||||
if res:
|
def create_db_info(db_data):
|
||||||
for db in res:
|
info = {}
|
||||||
self.info['databases'][db['name']] = {}
|
if is_field_included('size'):
|
||||||
|
info['size'] = int(db_data.get('size', 0) or 0)
|
||||||
|
if is_field_included('table_count'):
|
||||||
|
info['tables'] = int(db_data.get('tables', 0) or 0)
|
||||||
|
return info
|
||||||
|
|
||||||
if not exclude_fields or 'db_size' not in exclude_fields:
|
# Build the main query
|
||||||
if db['size'] is None:
|
query_parts = ['SELECT table_schema AS "name"']
|
||||||
db['size'] = 0
|
if is_field_included('size'):
|
||||||
|
query_parts.append('SUM(data_length + index_length) AS "size"')
|
||||||
|
if is_field_included('table_count'):
|
||||||
|
query_parts.append('COUNT(table_name) as "tables"')
|
||||||
|
|
||||||
self.info['databases'][db['name']]['size'] = int(db['size'])
|
query = "{} FROM information_schema.TABLES GROUP BY table_schema".format(", ".join(query_parts))
|
||||||
|
|
||||||
# If empty dbs are not needed in the returned dict, exit from the method
|
# Get and process databases with tables
|
||||||
if not return_empty_dbs:
|
databases = self.__exec_sql(query) or []
|
||||||
return None
|
for db in databases:
|
||||||
|
self.info['databases'][db['name']] = create_db_info(db)
|
||||||
|
|
||||||
# Add info about empty databases (issue #65727):
|
# Handle empty databases if requested
|
||||||
res = self.__exec_sql('SHOW DATABASES')
|
if return_empty_dbs:
|
||||||
if res:
|
empty_databases = self.__exec_sql('SHOW DATABASES') or []
|
||||||
for db in res:
|
for db in empty_databases:
|
||||||
if db['Database'] not in self.info['databases']:
|
db_name = db['Database']
|
||||||
self.info['databases'][db['Database']] = {}
|
if db_name not in self.info['databases']:
|
||||||
|
self.info['databases'][db_name] = create_db_info({})
|
||||||
if not exclude_fields or 'db_size' not in exclude_fields:
|
|
||||||
self.info['databases'][db['Database']]['size'] = 0
|
|
||||||
|
|
||||||
def __exec_sql(self, query, ddl=False):
|
def __exec_sql(self, query, ddl=False):
|
||||||
"""Execute SQL.
|
"""Execute SQL.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
@ -62,7 +62,6 @@ author:
|
||||||
- Andrew Klychkov (@Andersson007)
|
- Andrew Klychkov (@Andersson007)
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.mysql.mysql
|
- community.mysql.mysql
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
|
@ -117,8 +116,18 @@ rowcount:
|
||||||
returned: changed
|
returned: changed
|
||||||
type: list
|
type: list
|
||||||
sample: [5, 1]
|
sample: [5, 1]
|
||||||
|
execution_time_ms:
|
||||||
|
description:
|
||||||
|
- A list containing execution time per query in milliseconds.
|
||||||
|
- The measurements are done right before and after passing
|
||||||
|
the query to the driver for execution.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample: [7104, 85]
|
||||||
|
version_added: '3.12.0'
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
@ -139,6 +148,18 @@ DDL_QUERY_KEYWORDS = ('CREATE', 'DROP', 'ALTER', 'RENAME', 'TRUNCATE')
|
||||||
# Module execution.
|
# Module execution.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
def execute_and_return_time(cursor, query, args):
|
||||||
|
# Measure query execution time in milliseconds
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
|
||||||
|
cursor.execute(query, args)
|
||||||
|
|
||||||
|
# Calculate the execution time rounding it to 4 decimal places
|
||||||
|
exec_time_ms = round((time.perf_counter() - start_time) * 1000, 4)
|
||||||
|
return cursor, exec_time_ms
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = mysql_common_argument_spec()
|
argument_spec = mysql_common_argument_spec()
|
||||||
argument_spec.update(
|
argument_spec.update(
|
||||||
|
@ -213,6 +234,7 @@ def main():
|
||||||
query_result = []
|
query_result = []
|
||||||
executed_queries = []
|
executed_queries = []
|
||||||
rowcount = []
|
rowcount = []
|
||||||
|
execution_time_ms = []
|
||||||
|
|
||||||
already_exists = False
|
already_exists = False
|
||||||
for q in query:
|
for q in query:
|
||||||
|
@ -223,7 +245,8 @@ def main():
|
||||||
category=mysql_driver.Warning)
|
category=mysql_driver.Warning)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.execute(q, arguments)
|
cursor, exec_time_ms = execute_and_return_time(cursor, q, arguments)
|
||||||
|
execution_time_ms.append(exec_time_ms)
|
||||||
except mysql_driver.Warning:
|
except mysql_driver.Warning:
|
||||||
# When something is run with IF NOT EXISTS
|
# When something is run with IF NOT EXISTS
|
||||||
# and there's "already exists" MySQL warning,
|
# and there's "already exists" MySQL warning,
|
||||||
|
@ -280,6 +303,7 @@ def main():
|
||||||
'executed_queries': executed_queries,
|
'executed_queries': executed_queries,
|
||||||
'query_result': query_result,
|
'query_result': query_result,
|
||||||
'rowcount': rowcount,
|
'rowcount': rowcount,
|
||||||
|
'execution_time_ms': execution_time_ms,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Exit:
|
# Exit:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2013, Balazs Pocze <banyek@gawker.com>
|
# Copyright: (c) 2013, Balazs Pocze <banyek@gawker.com>
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# Certain parts are taken from Mark Theunissen's mysqldb module
|
# Certain parts are taken from Mark Theunissen's mysqldb module
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
@ -137,9 +137,10 @@ options:
|
||||||
aliases: [master_ssl_cipher]
|
aliases: [master_ssl_cipher]
|
||||||
primary_ssl_verify_server_cert:
|
primary_ssl_verify_server_cert:
|
||||||
description:
|
description:
|
||||||
- Same as mysql variable.
|
- Same as C(MASTER_SSL_VERIFY_SERVER_CERT) MySQL/MariaDB variable.
|
||||||
|
- The module switch automatically to C(SOURCE_SSL_VERIFY_SERVER_CERT) for MySQL 8.0.23 and later.
|
||||||
|
- Prior to community.mysql 3.14.0 C(false) had no effect.
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
|
||||||
version_added: '3.5.0'
|
version_added: '3.5.0'
|
||||||
primary_auto_position:
|
primary_auto_position:
|
||||||
description:
|
description:
|
||||||
|
@ -284,7 +285,6 @@ EXAMPLES = r'''
|
||||||
community.mysql.mysql_replication:
|
community.mysql.mysql_replication:
|
||||||
mode: changeprimary
|
mode: changeprimary
|
||||||
fail_on_error: true
|
fail_on_error: true
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
|
@ -494,7 +494,7 @@ def main():
|
||||||
primary_ssl_cert=dict(type='str', aliases=['master_ssl_cert']),
|
primary_ssl_cert=dict(type='str', aliases=['master_ssl_cert']),
|
||||||
primary_ssl_key=dict(type='str', no_log=False, aliases=['master_ssl_key']),
|
primary_ssl_key=dict(type='str', no_log=False, aliases=['master_ssl_key']),
|
||||||
primary_ssl_cipher=dict(type='str', aliases=['master_ssl_cipher']),
|
primary_ssl_cipher=dict(type='str', aliases=['master_ssl_cipher']),
|
||||||
primary_ssl_verify_server_cert=dict(type='bool', default=False),
|
primary_ssl_verify_server_cert=dict(type='bool'),
|
||||||
primary_use_gtid=dict(type='str', choices=[
|
primary_use_gtid=dict(type='str', choices=[
|
||||||
'current_pos', 'replica_pos', 'disabled'], aliases=['master_use_gtid']),
|
'current_pos', 'replica_pos', 'disabled'], aliases=['master_use_gtid']),
|
||||||
primary_delay=dict(type='int', aliases=['master_delay']),
|
primary_delay=dict(type='int', aliases=['master_delay']),
|
||||||
|
@ -642,8 +642,11 @@ def main():
|
||||||
chm.append("%s='%s'" % (command_resolver.resolve_command('MASTER_SSL_KEY'), primary_ssl_key))
|
chm.append("%s='%s'" % (command_resolver.resolve_command('MASTER_SSL_KEY'), primary_ssl_key))
|
||||||
if primary_ssl_cipher is not None:
|
if primary_ssl_cipher is not None:
|
||||||
chm.append("%s='%s'" % (command_resolver.resolve_command('MASTER_SSL_CIPHER'), primary_ssl_cipher))
|
chm.append("%s='%s'" % (command_resolver.resolve_command('MASTER_SSL_CIPHER'), primary_ssl_cipher))
|
||||||
if primary_ssl_verify_server_cert:
|
if primary_ssl_verify_server_cert is not None:
|
||||||
chm.append("%s=1" % command_resolver.resolve_command('MASTER_SSL_VERIFY_SERVER_CERT'))
|
if primary_ssl_verify_server_cert:
|
||||||
|
chm.append("%s=1" % command_resolver.resolve_command('MASTER_SSL_VERIFY_SERVER_CERT'))
|
||||||
|
else:
|
||||||
|
chm.append("%s=0" % command_resolver.resolve_command('MASTER_SSL_VERIFY_SERVER_CERT'))
|
||||||
if primary_auto_position:
|
if primary_auto_position:
|
||||||
chm.append("%s=1" % command_resolver.resolve_command('MASTER_AUTO_POSITION'))
|
chm.append("%s=1" % command_resolver.resolve_command('MASTER_AUTO_POSITION'))
|
||||||
if primary_use_gtid is not None:
|
if primary_use_gtid is not None:
|
||||||
|
@ -724,8 +727,11 @@ def main():
|
||||||
chm.append("SOURCE_SSL_KEY='%s'" % primary_ssl_key)
|
chm.append("SOURCE_SSL_KEY='%s'" % primary_ssl_key)
|
||||||
if primary_ssl_cipher is not None:
|
if primary_ssl_cipher is not None:
|
||||||
chm.append("SOURCE_SSL_CIPHER='%s'" % primary_ssl_cipher)
|
chm.append("SOURCE_SSL_CIPHER='%s'" % primary_ssl_cipher)
|
||||||
if primary_ssl_verify_server_cert:
|
if primary_ssl_verify_server_cert is not None:
|
||||||
chm.append("SOURCE_SSL_VERIFY_SERVER_CERT=1")
|
if primary_ssl_verify_server_cert:
|
||||||
|
chm.append("%s=1" % command_resolver.resolve_command('MASTER_SSL_VERIFY_SERVER_CERT'))
|
||||||
|
else:
|
||||||
|
chm.append("%s=0" % command_resolver.resolve_command('MASTER_SSL_VERIFY_SERVER_CERT'))
|
||||||
if primary_auto_position:
|
if primary_auto_position:
|
||||||
chm.append("SOURCE_AUTO_POSITION=1")
|
chm.append("SOURCE_AUTO_POSITION=1")
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2021, Andrew Klychkov <aaklychkov@mail.ru>
|
# Copyright: (c) 2021, Andrew Klychkov <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
from __future__ import absolute_import, division, print_function
|
||||||
|
@ -930,11 +930,12 @@ class Role():
|
||||||
set_default_role_all=set_default_role_all)
|
set_default_role_all=set_default_role_all)
|
||||||
|
|
||||||
if privs:
|
if privs:
|
||||||
result = user_mod(self.cursor, self.name, self.host,
|
result = user_mod(cursor=self.cursor, user=self.name, host=self.host,
|
||||||
None, None, None, None, None, None, None,
|
host_all=None, password=None, encrypted=None, plugin=None,
|
||||||
privs, append_privs, subtract_privs, None, None,
|
plugin_auth_string=None, plugin_hash_string=None, salt=None,
|
||||||
self.module, None, None, role=True,
|
new_priv=privs, append_privs=append_privs, subtract_privs=subtract_privs,
|
||||||
maria_role=self.is_mariadb)
|
attributes=None, tls_requires=None, module=self.module, password_expire=None,
|
||||||
|
password_expire_interval=None, role=True, maria_role=self.is_mariadb)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
|
|
||||||
if admin:
|
if admin:
|
||||||
|
|
|
@ -46,6 +46,7 @@ options:
|
||||||
priv:
|
priv:
|
||||||
description:
|
description:
|
||||||
- "MySQL privileges string in the format: C(db.table:priv1,priv2)."
|
- "MySQL privileges string in the format: C(db.table:priv1,priv2)."
|
||||||
|
- Additionally, there must be no spaces between the table and the privilege as this will yield a non-idempotent check mode.
|
||||||
- "Multiple privileges can be specified by separating each one using
|
- "Multiple privileges can be specified by separating each one using
|
||||||
a forward slash: C(db.table1:priv/db.table2:priv)."
|
a forward slash: C(db.table1:priv/db.table2:priv)."
|
||||||
- The format is based on MySQL C(GRANT) statement.
|
- The format is based on MySQL C(GRANT) statement.
|
||||||
|
@ -188,6 +189,15 @@ options:
|
||||||
fields names in privileges.
|
fields names in privileges.
|
||||||
type: bool
|
type: bool
|
||||||
version_added: '3.8.0'
|
version_added: '3.8.0'
|
||||||
|
|
||||||
|
locked:
|
||||||
|
description:
|
||||||
|
- Lock account to prevent connections using it.
|
||||||
|
- This is primarily used for creating a user that will act as a DEFINER on stored procedures.
|
||||||
|
- If not specified leaves the lock state as is (for a new user creates unlocked).
|
||||||
|
type: bool
|
||||||
|
version_added: '3.13.0'
|
||||||
|
|
||||||
attributes:
|
attributes:
|
||||||
description:
|
description:
|
||||||
- "Create, update, or delete user attributes (arbitrary 'key: value' comments) for the user."
|
- "Create, update, or delete user attributes (arbitrary 'key: value' comments) for the user."
|
||||||
|
@ -224,6 +234,7 @@ author:
|
||||||
- Lukasz Tomaszkiewicz (@tomaszkiewicz)
|
- Lukasz Tomaszkiewicz (@tomaszkiewicz)
|
||||||
- kmarse (@kmarse)
|
- kmarse (@kmarse)
|
||||||
- Laurent Indermühle (@laurent-indermuehle)
|
- Laurent Indermühle (@laurent-indermuehle)
|
||||||
|
- E.S. Rosenberg (@Keeper-of-the-Keys)
|
||||||
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.mysql.mysql
|
- community.mysql.mysql
|
||||||
|
@ -268,7 +279,7 @@ EXAMPLES = r'''
|
||||||
priv: '*.*:ALL,GRANT'
|
priv: '*.*:ALL,GRANT'
|
||||||
state: present
|
state: present
|
||||||
session_vars:
|
session_vars:
|
||||||
wsrep_on: off
|
wsrep_on: 'off'
|
||||||
|
|
||||||
- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2
|
- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2
|
||||||
community.mysql.mysql_user:
|
community.mysql.mysql_user:
|
||||||
|
@ -399,6 +410,13 @@ EXAMPLES = r'''
|
||||||
priv:
|
priv:
|
||||||
'db1.*': DELETE
|
'db1.*': DELETE
|
||||||
|
|
||||||
|
- name: Create locked user to act as a definer on procedures
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
name: readonly_procedures_locked
|
||||||
|
locked: true
|
||||||
|
priv:
|
||||||
|
db1.*: SELECT
|
||||||
|
|
||||||
# Example .my.cnf file for setting the root password
|
# Example .my.cnf file for setting the root password
|
||||||
# [client]
|
# [client]
|
||||||
# user=root
|
# user=root
|
||||||
|
@ -469,6 +487,7 @@ def main():
|
||||||
column_case_sensitive=dict(type='bool', default=None), # TODO 4.0.0 add default=True
|
column_case_sensitive=dict(type='bool', default=None), # TODO 4.0.0 add default=True
|
||||||
password_expire=dict(type='str', choices=['now', 'never', 'default', 'interval'], no_log=True),
|
password_expire=dict(type='str', choices=['now', 'never', 'default', 'interval'], no_log=True),
|
||||||
password_expire_interval=dict(type='int', required_if=[('password_expire', 'interval', True)], no_log=True),
|
password_expire_interval=dict(type='int', required_if=[('password_expire', 'interval', True)], no_log=True),
|
||||||
|
locked=dict(type='bool'),
|
||||||
)
|
)
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
|
@ -509,6 +528,7 @@ def main():
|
||||||
column_case_sensitive = module.params["column_case_sensitive"]
|
column_case_sensitive = module.params["column_case_sensitive"]
|
||||||
password_expire = module.params["password_expire"]
|
password_expire = module.params["password_expire"]
|
||||||
password_expire_interval = module.params["password_expire_interval"]
|
password_expire_interval = module.params["password_expire_interval"]
|
||||||
|
locked = module.boolean(module.params['locked'])
|
||||||
|
|
||||||
if priv and not isinstance(priv, (str, dict)):
|
if priv and not isinstance(priv, (str, dict)):
|
||||||
module.fail_json(msg="priv parameter must be str or dict but %s was passed" % type(priv))
|
module.fail_json(msg="priv parameter must be str or dict but %s was passed" % type(priv))
|
||||||
|
@ -576,13 +596,15 @@ def main():
|
||||||
result = user_mod(cursor, user, host, host_all, password, encrypted,
|
result = user_mod(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, salt,
|
plugin, plugin_hash_string, plugin_auth_string, salt,
|
||||||
priv, append_privs, subtract_privs, attributes, tls_requires, module,
|
priv, append_privs, subtract_privs, attributes, tls_requires, module,
|
||||||
password_expire, password_expire_interval)
|
password_expire, password_expire_interval, locked=locked)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
result = user_mod(cursor, user, host, host_all, None, encrypted,
|
result = user_mod(cursor=cursor, user=user, host=host, host_all=host_all, password=None,
|
||||||
None, None, None, None,
|
encrypted=encrypted, plugin=None, plugin_hash_string=None, plugin_auth_string=None,
|
||||||
priv, append_privs, subtract_privs, attributes, tls_requires, module,
|
salt=None, new_priv=priv, append_privs=append_privs, subtract_privs=subtract_privs,
|
||||||
password_expire, password_expire_interval)
|
attributes=attributes, tls_requires=tls_requires, module=module,
|
||||||
|
password_expire=password_expire, password_expire_interval=password_expire_interval,
|
||||||
|
locked=locked)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
msg = result['msg']
|
msg = result['msg']
|
||||||
password_changed = result['password_changed']
|
password_changed = result['password_changed']
|
||||||
|
@ -600,7 +622,7 @@ def main():
|
||||||
result = user_add(cursor, user, host, host_all, password, encrypted,
|
result = user_add(cursor, user, host, host_all, password, encrypted,
|
||||||
plugin, plugin_hash_string, plugin_auth_string, salt,
|
plugin, plugin_hash_string, plugin_auth_string, salt,
|
||||||
priv, attributes, tls_requires, reuse_existing_password, module,
|
priv, attributes, tls_requires, reuse_existing_password, module,
|
||||||
password_expire, password_expire_interval)
|
password_expire, password_expire_interval, locked=locked)
|
||||||
changed = result['changed']
|
changed = result['changed']
|
||||||
password_changed = result['password_changed']
|
password_changed = result['password_changed']
|
||||||
final_attributes = result['attributes']
|
final_attributes = result['attributes']
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# Initial CI tests of mysql_replication module
|
# Initial CI tests of mysql_replication module
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# Tests for master_use_gtid parameter.
|
# Tests for master_use_gtid parameter.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# Needs for further tests:
|
# Needs for further tests:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# Preparation:
|
# Preparation:
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
- connector_name == 'mysqlclient'
|
- connector_name == 'mysqlclient'
|
||||||
|
|
||||||
- name: Get the python version in use
|
- name: Get the python version in use
|
||||||
ansible.builtin.command:
|
ansible.builtin.shell:
|
||||||
cmd: python -V
|
cmd: echo $( $(command -v python || command -v python3) -V )
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: false
|
failed_when: false
|
||||||
register: python_version_in_use
|
register: python_version_in_use
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: >
|
msg: >
|
||||||
Python in use inside the test container:
|
Python in use inside the test container:
|
||||||
${{ python_version_in_use }}
|
{{ python_version_in_use.stdout }}
|
||||||
when:
|
when:
|
||||||
- python_version_in_use is defined
|
- python_version_in_use is defined
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
- name: assert that databases does not exist
|
- name: assert that databases does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' not in mysql_result.stdout"
|
- db1_name not in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' not in mysql_result.stdout"
|
- db3_name not in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Create multiple databases that does not exists (check mode)
|
# Create multiple databases that does not exists (check mode)
|
||||||
|
@ -65,9 +65,9 @@
|
||||||
- name: assert that databases does not exist (since created via check mode)
|
- name: assert that databases does not exist (since created via check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' not in mysql_result.stdout"
|
- db1_name not in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' not in mysql_result.stdout"
|
- db3_name not in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Create multiple databases
|
# Create multiple databases
|
||||||
|
@ -88,7 +88,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}']
|
- result.db_list == [db1_name, db2_name, db3_name]
|
||||||
|
|
||||||
- name: run command to list databases like specified database name
|
- name: run command to list databases like specified database name
|
||||||
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
||||||
|
@ -97,9 +97,9 @@
|
||||||
- name: assert that databases exist after creation
|
- name: assert that databases exist after creation
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# Recreate already existing databases (check mode)
|
# Recreate already existing databases (check mode)
|
||||||
|
@ -129,9 +129,9 @@
|
||||||
- name: assert that databases exist (since performed recreation of existing databases via check mode)
|
- name: assert that databases exist (since performed recreation of existing databases via check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Recreate same databases
|
# Recreate same databases
|
||||||
|
@ -160,9 +160,9 @@
|
||||||
- name: assert that databases does priorly exist
|
- name: assert that databases does priorly exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Delete one of the databases (db2 here)
|
# Delete one of the databases (db2 here)
|
||||||
|
@ -189,9 +189,9 @@
|
||||||
- name: assert that only db2 database does not exist
|
- name: assert that only db2 database does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# Recreate multiple databases in which few databases does not exists (check mode)
|
# Recreate multiple databases in which few databases does not exists (check mode)
|
||||||
|
@ -221,9 +221,9 @@
|
||||||
- name: assert that recreated non existing databases does not exist (since created via check mode)
|
- name: assert that recreated non existing databases does not exist (since created via check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Create multiple databases
|
# Create multiple databases
|
||||||
|
@ -252,9 +252,9 @@
|
||||||
- name: assert that databases exist
|
- name: assert that databases exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# ============================== DUMP TEST =================================
|
# ============================== DUMP TEST =================================
|
||||||
#
|
#
|
||||||
|
@ -293,9 +293,9 @@
|
||||||
- name: assert that databases exist (check mode)
|
- name: assert that databases exist (check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
- name: state dump - file name should not exist (since dumped via check mode)
|
- name: state dump - file name should not exist (since dumped via check mode)
|
||||||
file:
|
file:
|
||||||
|
@ -332,10 +332,10 @@
|
||||||
- name: assert that databases exist (since check mode)
|
- name: assert that databases exist (since check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
|
|
||||||
- name: state dump - file name should not exist (since prior dump operation performed via check mode)
|
- name: state dump - file name should not exist (since prior dump operation performed via check mode)
|
||||||
file:
|
file:
|
||||||
|
@ -371,11 +371,11 @@
|
||||||
- name: assert that databases exist (since delete via check mode)
|
- name: assert that databases exist (since delete via check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
- "'{{ db5_name }}' not in mysql_result.stdout"
|
- db5_name not in mysql_result.stdout
|
||||||
|
|
||||||
- name: state dump - file name should not exist (since prior dump operation performed via check mode)
|
- name: state dump - file name should not exist (since prior dump operation performed via check mode)
|
||||||
file:
|
file:
|
||||||
|
@ -403,7 +403,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- dump_result is changed
|
- dump_result is changed
|
||||||
- dump_result.db_list == ['{{ db1_name }}', '{{ db2_name }}', '{{ db3_name }}']
|
- dump_result.db_list == [db1_name, db2_name, db3_name]
|
||||||
|
|
||||||
- name: Run command to list databases like specified database name
|
- name: Run command to list databases like specified database name
|
||||||
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
||||||
|
@ -412,9 +412,9 @@
|
||||||
- name: assert that databases exist
|
- name: assert that databases exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
- name: State dump - file name should exist (dump1_file)
|
- name: State dump - file name should exist (dump1_file)
|
||||||
file:
|
file:
|
||||||
|
@ -461,11 +461,11 @@
|
||||||
- name: assert that databases exist
|
- name: assert that databases exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' in mysql_result.stdout"
|
- db1_name in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
- "'{{ db5_name }}' not in mysql_result.stdout"
|
- db5_name not in mysql_result.stdout
|
||||||
|
|
||||||
- name: state dump - file name should exist (dump2_file)
|
- name: state dump - file name should exist (dump2_file)
|
||||||
file:
|
file:
|
||||||
|
@ -501,8 +501,8 @@
|
||||||
- name: assert that databases exist even after deleting (since deleted via check mode)
|
- name: assert that databases exist even after deleting (since deleted via check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db2_name }}' in mysql_result.stdout"
|
- db2_name in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' in mysql_result.stdout"
|
- db3_name in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Delete multiple databases
|
# Delete multiple databases
|
||||||
|
@ -522,7 +522,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.db_list == ['{{ db2_name }}', '{{ db3_name }}']
|
- result.db_list == [db2_name, db3_name]
|
||||||
|
|
||||||
- name: run command to list databases like specified database name
|
- name: run command to list databases like specified database name
|
||||||
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
command: "{{ mysql_command }} \"-e show databases like 'database%'\""
|
||||||
|
@ -531,8 +531,8 @@
|
||||||
- name: assert that databases does not exist
|
- name: assert that databases does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' not in mysql_result.stdout"
|
- db3_name not in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Delete non existing databases (check mode)
|
# Delete non existing databases (check mode)
|
||||||
|
@ -561,8 +561,8 @@
|
||||||
- name: assert that databases does not exist since were deleted priorly (check mode)
|
- name: assert that databases does not exist since were deleted priorly (check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Delete already deleted databases
|
# Delete already deleted databases
|
||||||
|
@ -590,8 +590,8 @@
|
||||||
- name: assert that databases does not exists
|
- name: assert that databases does not exists
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
# Delete all databases
|
# Delete all databases
|
||||||
|
@ -622,11 +622,11 @@
|
||||||
- name: assert that specific databases does not exist
|
- name: assert that specific databases does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db1_name }}' not in mysql_result.stdout"
|
- db1_name not in mysql_result.stdout
|
||||||
- "'{{ db2_name }}' not in mysql_result.stdout"
|
- db2_name not in mysql_result.stdout
|
||||||
- "'{{ db3_name }}' not in mysql_result.stdout"
|
- db3_name not in mysql_result.stdout
|
||||||
- "'{{ db4_name }}' not in mysql_result.stdout"
|
- db4_name not in mysql_result.stdout
|
||||||
- "'{{ db5_name }}' not in mysql_result.stdout"
|
- db5_name not in mysql_result.stdout
|
||||||
|
|
||||||
- name: state dump - dump 1 file name should be removed
|
- name: state dump - dump 1 file name should be removed
|
||||||
file:
|
file:
|
||||||
|
|
|
@ -283,7 +283,7 @@
|
||||||
- name: Dump and Import | Assert that db_name2 database does not exist
|
- name: Dump and Import | Assert that db_name2 database does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_name2 }}' not in mysql_result.stdout"
|
- db_name2 not in mysql_result.stdout
|
||||||
|
|
||||||
- name: Dump and Import | Test state=import to restore a database from dumped file2 (check mode)
|
- name: Dump and Import | Test state=import to restore a database from dumped file2 (check mode)
|
||||||
mysql_db:
|
mysql_db:
|
||||||
|
@ -309,7 +309,7 @@
|
||||||
- name: Dump and Import | Assert that db_name2 database does not exist (check mode)
|
- name: Dump and Import | Assert that db_name2 database does not exist (check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_name2 }}' not in mysql_result.stdout"
|
- db_name2 not in mysql_result.stdout
|
||||||
|
|
||||||
- name: Dump and Import | Test state=import to restore a database from multiple database dumped file2
|
- name: Dump and Import | Test state=import to restore a database from multiple database dumped file2
|
||||||
mysql_db:
|
mysql_db:
|
||||||
|
@ -326,7 +326,7 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- import_result2 is changed
|
- import_result2 is changed
|
||||||
- import_result2.db_list == ['{{ db_name2 }}']
|
- import_result2.db_list == [db_name2]
|
||||||
|
|
||||||
- name: Dump and Import | Run command to list databases
|
- name: Dump and Import | Run command to list databases
|
||||||
command: "{{ mysql_command }} \"-e show databases like 'data%'\""
|
command: "{{ mysql_command }} \"-e show databases like 'data%'\""
|
||||||
|
@ -335,7 +335,7 @@
|
||||||
- name: Dump and Import | Assert that db_name2 database does exist after import
|
- name: Dump and Import | Assert that db_name2 database does exist after import
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_name2 }}' in mysql_result.stdout"
|
- db_name2 in mysql_result.stdout
|
||||||
|
|
||||||
- name: Dump and Import | Test state=dump to backup the database of type {{ format_type }} (expect changed=true)
|
- name: Dump and Import | Test state=dump to backup the database of type {{ format_type }} (expect changed=true)
|
||||||
mysql_db:
|
mysql_db:
|
||||||
|
@ -487,18 +487,22 @@
|
||||||
login_password: '{{ mysql_password }}'
|
login_password: '{{ mysql_password }}'
|
||||||
login_host: '{{ mysql_host }}'
|
login_host: '{{ mysql_host }}'
|
||||||
login_port: '{{ mysql_primary_port }}'
|
login_port: '{{ mysql_primary_port }}'
|
||||||
name: '{{ item }}'
|
name: '{{ cleanup_db }}'
|
||||||
state: absent
|
state: absent
|
||||||
loop:
|
loop:
|
||||||
- '{{ db_name }}'
|
- '{{ db_name }}'
|
||||||
- '{{ db_name2 }}'
|
- '{{ db_name2 }}'
|
||||||
|
loop_control:
|
||||||
|
loop_var: cleanup_db
|
||||||
|
|
||||||
- name: Dump and Import | Clean up files
|
- name: Dump and Import | Clean up files
|
||||||
file:
|
file:
|
||||||
name: '{{ item }}'
|
name: '{{ cleanup_file }}'
|
||||||
state: absent
|
state: absent
|
||||||
loop:
|
loop:
|
||||||
- '{{ db_file_name }}'
|
- '{{ db_file_name }}'
|
||||||
- '{{ wrong_sql_file }}'
|
- '{{ wrong_sql_file }}'
|
||||||
- '{{ dump_file1 }}'
|
- '{{ dump_file1 }}'
|
||||||
- '{{ dump_file2 }}'
|
- '{{ dump_file2 }}'
|
||||||
|
loop_control:
|
||||||
|
loop_var: cleanup_file
|
||||||
|
|
|
@ -41,8 +41,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.db == '{{ db_name }}'
|
- result.db == db_name
|
||||||
- result.executed_commands == ["CREATE DATABASE `{{ db_name }}`"]
|
- result.executed_commands == expected_commands
|
||||||
|
vars:
|
||||||
|
expected_commands: ["CREATE DATABASE `{{ db_name }}`"]
|
||||||
|
|
||||||
- name: State Present Absent | Run command to test state=present for a database name (expect db_name in stdout)
|
- name: State Present Absent | Run command to test state=present for a database name (expect db_name in stdout)
|
||||||
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
||||||
|
@ -51,7 +53,7 @@
|
||||||
- name: State Present Absent | Assert database exist
|
- name: State Present Absent | Assert database exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_name }}' in result.stdout"
|
- db_name in result.stdout
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: State Present Absent | Test state=absent for a database name (expect changed=true)
|
- name: State Present Absent | Test state=absent for a database name (expect changed=true)
|
||||||
|
@ -68,8 +70,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.db == '{{ db_name }}'
|
- result.db == db_name
|
||||||
- result.executed_commands == ["DROP DATABASE `{{ db_name }}`"]
|
- result.executed_commands == expected_commands
|
||||||
|
vars:
|
||||||
|
expected_commands: ["DROP DATABASE `{{ db_name }}`"]
|
||||||
|
|
||||||
- name: State Present Absent | Run command to test state=absent for a database name (expect db_name not in stdout)
|
- name: State Present Absent | Run command to test state=absent for a database name (expect db_name not in stdout)
|
||||||
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
||||||
|
@ -78,7 +82,7 @@
|
||||||
- name: State Present Absent | Assert database does not exist
|
- name: State Present Absent | Assert database does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_name }}' not in result.stdout"
|
- db_name not in result.stdout
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: State Present Absent | Test mysql_db encoding param not valid - issue 8075
|
- name: State Present Absent | Test mysql_db encoding param not valid - issue 8075
|
||||||
|
@ -116,7 +120,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"]
|
- result.executed_commands == expected_commands
|
||||||
|
vars:
|
||||||
|
expected_commands: ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'utf8'"]
|
||||||
|
|
||||||
- name: State Present Absent | Test database was created
|
- name: State Present Absent | Test database was created
|
||||||
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
|
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
|
||||||
|
@ -152,7 +158,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_commands == ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"]
|
- result.executed_commands == expected_commands
|
||||||
|
vars:
|
||||||
|
expected_commands: ["CREATE DATABASE `en{{ db_name }}` CHARACTER SET 'binary'"]
|
||||||
|
|
||||||
- name: State Present Absent | Run command to test database was created
|
- name: State Present Absent | Run command to test database was created
|
||||||
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
|
command: "{{ mysql_command }} -e \"SHOW CREATE DATABASE `en{{ db_name }}`\""
|
||||||
|
@ -207,7 +215,7 @@
|
||||||
- name: State Present Absent | Assert database exist
|
- name: State Present Absent | Assert database exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_user1 }}' in result.stdout"
|
- db_user1 in result.stdout
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: State Present Absent | Create user2 to access database with privilege select only
|
- name: State Present Absent | Create user2 to access database with privilege select only
|
||||||
|
@ -245,7 +253,7 @@
|
||||||
- name: State Present Absent | Assert database does not exist
|
- name: State Present Absent | Assert database does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_user2 }}' not in result.stdout"
|
- db_user2 not in result.stdout
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: State Present Absent | Delete database using user2 with no privilege to delete (expect failed=true)
|
- name: State Present Absent | Delete database using user2 with no privilege to delete (expect failed=true)
|
||||||
|
@ -272,7 +280,7 @@
|
||||||
- name: State Present Absent | Assert database still exist
|
- name: State Present Absent | Assert database still exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_user1 }}' in result.stdout"
|
- db_user1 in result.stdout
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: State Present Absent | Delete database using user1 with all privilege to delete a database (expect changed=true)
|
- name: State Present Absent | Delete database using user1 with all privilege to delete a database (expect changed=true)
|
||||||
|
@ -290,7 +298,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_commands == ["DROP DATABASE `{{ db_user1 }}`"]
|
- result.executed_commands == expected_commands
|
||||||
|
vars:
|
||||||
|
expected_commands: ["DROP DATABASE `{{ db_user1 }}`"]
|
||||||
|
|
||||||
- name: State Present Absent | Run command to test database was deleted using user1
|
- name: State Present Absent | Run command to test database was deleted using user1
|
||||||
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
command: "{{ mysql_command }} -e \"show databases like '{{ db_name | regex_replace(\"([%_\\\\])\", \"\\\\\\1\") }}'\""
|
||||||
|
@ -299,4 +309,4 @@
|
||||||
- name: State Present Absent | Assert database does not exist
|
- name: State Present Absent | Assert database does not exist
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ db_user1 }}' not in result.stdout"
|
- db_user1 not in result.stdout
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- module_defaults:
|
||||||
|
community.mysql.mysql_db: &mysql_defaults
|
||||||
|
login_user: "{{ mysql_user }}"
|
||||||
|
login_password: "{{ mysql_password }}"
|
||||||
|
login_host: "{{ mysql_host }}"
|
||||||
|
login_port: "{{ mysql_primary_port }}"
|
||||||
|
community.mysql.mysql_query: *mysql_defaults
|
||||||
|
community.mysql.mysql_info: *mysql_defaults
|
||||||
|
community.mysql.mysql_user: *mysql_defaults
|
||||||
|
|
||||||
|
block:
|
||||||
|
|
||||||
|
# ================================ Prepare ==============================
|
||||||
|
- name: Mysql_info databases | Prepare | Create databases
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
name:
|
||||||
|
- db_tables_count_empty
|
||||||
|
- db_tables_count_1
|
||||||
|
- db_tables_count_2
|
||||||
|
- db_only_views # https://github.com/ansible-Getions/community.mysql/issues/204
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Prepare | Create tables
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
query:
|
||||||
|
- >-
|
||||||
|
CREATE TABLE IF NOT EXISTS db_tables_count_1.t1
|
||||||
|
(id int, name varchar(9))
|
||||||
|
- >-
|
||||||
|
CREATE TABLE IF NOT EXISTS db_tables_count_2.t1
|
||||||
|
(id int, name1 varchar(9))
|
||||||
|
- >-
|
||||||
|
CREATE TABLE IF NOT EXISTS db_tables_count_2.t2
|
||||||
|
(id int, name1 varchar(9))
|
||||||
|
- >-
|
||||||
|
CREATE VIEW db_only_views.v_today (today) AS SELECT CURRENT_DATE
|
||||||
|
|
||||||
|
# ================================== Tests ==============================
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Get all non-empty databases fields
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size != 16384 or
|
||||||
|
result.databases['db_tables_count_1'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_2'].size != 32768 or
|
||||||
|
result.databases['db_tables_count_2'].tables != 2 or
|
||||||
|
result.databases['db_only_views'].size != 0 or
|
||||||
|
result.databases['db_only_views'].tables != 1 or
|
||||||
|
'db_tables_count_empty' in result.databases | dict2items
|
||||||
|
| map(attribute='key')
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Get all dbs fields except db_size
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
exclude_fields:
|
||||||
|
- db_size
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size is defined or
|
||||||
|
result.databases['db_tables_count_1'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_2'].size is defined or
|
||||||
|
result.databases['db_tables_count_2'].tables != 2 or
|
||||||
|
result.databases['db_only_views'].size is defined or
|
||||||
|
result.databases['db_only_views'].tables != 1 or
|
||||||
|
'db_tables_count_empty' in result.databases | dict2items
|
||||||
|
| map(attribute='key')
|
||||||
|
|
||||||
|
# 'unsupported' element is passed to check that an unsupported value
|
||||||
|
# won't break anything (will be ignored regarding to the module's
|
||||||
|
# documentation).
|
||||||
|
- name: Mysql_info databases | Get all dbs fields with unsupported value
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
exclude_fields:
|
||||||
|
- db_size
|
||||||
|
- unsupported
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size is defined or
|
||||||
|
result.databases['db_tables_count_1'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_2'].size is defined or
|
||||||
|
result.databases['db_tables_count_2'].tables != 2 or
|
||||||
|
result.databases['db_only_views'].size is defined or
|
||||||
|
result.databases['db_only_views'].tables != 1 or
|
||||||
|
'db_tables_count_empty' in result.databases | dict2items
|
||||||
|
| map(attribute='key')
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Get all dbs fields except tables
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
exclude_fields:
|
||||||
|
- db_table_count
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size != 16384 or
|
||||||
|
result.databases['db_tables_count_1'].tables is defined or
|
||||||
|
result.databases['db_tables_count_2'].size != 32768 or
|
||||||
|
result.databases['db_tables_count_2'].tables is defined or
|
||||||
|
result.databases['db_only_views'].size != 0 or
|
||||||
|
result.databases['db_only_views'].tables is defined or
|
||||||
|
'db_tables_count_empty' in result.databases | dict2items
|
||||||
|
| map(attribute='key')
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Get all dbs even empty ones
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
return_empty_dbs: true
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size != 16384 or
|
||||||
|
result.databases['db_tables_count_1'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_2'].size != 32768 or
|
||||||
|
result.databases['db_tables_count_2'].tables != 2 or
|
||||||
|
result.databases['db_only_views'].size != 0 or
|
||||||
|
result.databases['db_only_views'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_empty'].size != 0 or
|
||||||
|
result.databases['db_tables_count_empty'].tables != 0
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Get all dbs even empty ones without size
|
||||||
|
community.mysql.mysql_info:
|
||||||
|
filter:
|
||||||
|
- databases
|
||||||
|
exclude_fields:
|
||||||
|
- db_size
|
||||||
|
return_empty_dbs: true
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- >
|
||||||
|
result.databases['db_tables_count_1'].size is defined or
|
||||||
|
result.databases['db_tables_count_1'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_2'].size is defined or
|
||||||
|
result.databases['db_tables_count_2'].tables != 2 or
|
||||||
|
result.databases['db_only_views'].size is defined or
|
||||||
|
result.databases['db_only_views'].tables != 1 or
|
||||||
|
result.databases['db_tables_count_empty'].size is defined or
|
||||||
|
result.databases['db_tables_count_empty'].tables != 0
|
||||||
|
|
||||||
|
# ================================== Cleanup ============================
|
||||||
|
|
||||||
|
- name: Mysql_info databases | Cleanup databases
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
name:
|
||||||
|
- db_tables_count_empty
|
||||||
|
- db_tables_count_1
|
||||||
|
- db_tables_count_2
|
||||||
|
- db_only_views
|
||||||
|
state: absent
|
|
@ -31,6 +31,19 @@
|
||||||
CREATE TABLE IF NOT EXISTS users_info_db.T_UPPER
|
CREATE TABLE IF NOT EXISTS users_info_db.T_UPPER
|
||||||
(id int, name1 varchar(9), NAME2 varchar(9), Name3 varchar(9))
|
(id int, name1 varchar(9), NAME2 varchar(9), Name3 varchar(9))
|
||||||
|
|
||||||
|
# No need for a specific test later. When the module will retrieve the
|
||||||
|
# users privileges, it will fail with an error "1141 - There is no such
|
||||||
|
# grant defined for user 'PUBLIC' on host'%'" if the PUBLIC role is not
|
||||||
|
# handled properly by our module.
|
||||||
|
- name: Mysql_info users_info | Grant to PUBLIC for MariaDB 10.11+
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
query:
|
||||||
|
- >-
|
||||||
|
GRANT SELECT,INSERT,UPDATE,DELETE on users_info_db.* TO PUBLIC
|
||||||
|
when:
|
||||||
|
- db_engine == 'mariadb'
|
||||||
|
- db_version is version('10.11.1', '>=')
|
||||||
|
|
||||||
# I failed to create a procedure using community.mysql.mysql_query.
|
# I failed to create a procedure using community.mysql.mysql_query.
|
||||||
# Maybe it's because we must changed the delimiter.
|
# Maybe it's because we must changed the delimiter.
|
||||||
- name: Mysql_info users_info | Create procedure SQL file
|
- name: Mysql_info users_info | Create procedure SQL file
|
||||||
|
@ -261,6 +274,7 @@
|
||||||
resource_limits: "{{ item.resource_limits | default(omit) }}"
|
resource_limits: "{{ item.resource_limits | default(omit) }}"
|
||||||
column_case_sensitive: true
|
column_case_sensitive: true
|
||||||
state: present
|
state: present
|
||||||
|
locked: "{{ item.locked | default(omit) }}"
|
||||||
loop: "{{ result.users_info }}"
|
loop: "{{ result.users_info }}"
|
||||||
loop_control:
|
loop_control:
|
||||||
label: "{{ item.name }}@{{ item.host }}"
|
label: "{{ item.name }}@{{ item.host }}"
|
||||||
|
@ -275,7 +289,8 @@
|
||||||
- item.name != 'mariadb.sys'
|
- item.name != 'mariadb.sys'
|
||||||
- item.name != 'mysql.sys'
|
- item.name != 'mysql.sys'
|
||||||
- item.name != 'mysql.infoschema'
|
- item.name != 'mysql.infoschema'
|
||||||
|
- item.name != 'mysql.session'
|
||||||
|
- item.name != 'PUBLIC' # MariaDB roles are not supported
|
||||||
|
|
||||||
# ================================== Cleanup ============================
|
# ================================== Cleanup ============================
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
####################################################################
|
####################################################################
|
||||||
|
|
||||||
# Test code for mysql_info module
|
# Test code for mysql_info module
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
###################
|
###################
|
||||||
|
@ -132,94 +132,11 @@
|
||||||
- result.global_status is not defined
|
- result.global_status is not defined
|
||||||
- result.users is not defined
|
- result.users is not defined
|
||||||
|
|
||||||
# Test exclude_fields: db_size
|
|
||||||
# 'unsupported' element is passed to check that an unsupported value
|
|
||||||
# won't break anything (will be ignored regarding to the module's documentation).
|
|
||||||
- name: Collect info about databases excluding their sizes
|
|
||||||
mysql_info:
|
|
||||||
<<: *mysql_params
|
|
||||||
filter:
|
|
||||||
- databases
|
|
||||||
exclude_fields:
|
|
||||||
- db_size
|
|
||||||
- unsupported
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is not changed
|
|
||||||
- result.databases != {}
|
|
||||||
- result.databases.mysql == {}
|
|
||||||
|
|
||||||
########################################################
|
|
||||||
# Issue #65727, empty databases must be in returned dict
|
|
||||||
#
|
|
||||||
- name: Create empty database acme
|
|
||||||
mysql_db:
|
|
||||||
<<: *mysql_params
|
|
||||||
name: acme
|
|
||||||
|
|
||||||
- name: Collect info about databases
|
|
||||||
mysql_info:
|
|
||||||
<<: *mysql_params
|
|
||||||
filter:
|
|
||||||
- databases
|
|
||||||
return_empty_dbs: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
# Check acme is in returned dict
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is not changed
|
|
||||||
- result.databases.acme.size == 0
|
|
||||||
- result.databases.mysql != {}
|
|
||||||
|
|
||||||
- name: Collect info about databases excluding their sizes
|
|
||||||
mysql_info:
|
|
||||||
<<: *mysql_params
|
|
||||||
filter:
|
|
||||||
- databases
|
|
||||||
exclude_fields:
|
|
||||||
- db_size
|
|
||||||
return_empty_dbs: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
# Check acme is in returned dict
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is not changed
|
|
||||||
- result.databases.acme == {}
|
|
||||||
- result.databases.mysql == {}
|
|
||||||
|
|
||||||
- name: Remove acme database
|
|
||||||
mysql_db:
|
|
||||||
<<: *mysql_params
|
|
||||||
name: acme
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- include_tasks: issue-28.yml
|
- include_tasks: issue-28.yml
|
||||||
|
|
||||||
# https://github.com/ansible-collections/community.mysql/issues/204
|
- name: Import tasks file to tests tables count in database filter
|
||||||
- name: Create database containing only views
|
ansible.builtin.import_tasks:
|
||||||
mysql_db:
|
file: filter_databases.yml
|
||||||
<<: *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
|
|
||||||
|
|
||||||
- name: Import tasks file to tests users_info filter
|
- name: Import tasks file to tests users_info filter
|
||||||
ansible.builtin.import_tasks:
|
ansible.builtin.import_tasks:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
# Test code for mysql_query module
|
# Test code for mysql_query module
|
||||||
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
- vars:
|
- vars:
|
||||||
mysql_parameters: &mysql_params
|
mysql_parameters: &mysql_params
|
||||||
|
@ -21,7 +21,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['CREATE DATABASE {{ test_db }}']
|
- result.executed_queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ['CREATE DATABASE {{ test_db }}']
|
||||||
|
|
||||||
- name: Create {{ test_table1 }}
|
- name: Create {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -34,7 +36,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['CREATE TABLE {{ test_table1 }} (id int)']
|
- result.executed_queries == expected_queries
|
||||||
|
- result.execution_time_ms[0] > 0
|
||||||
|
vars:
|
||||||
|
expected_queries: ['CREATE TABLE {{ test_table1 }} (id int)']
|
||||||
|
|
||||||
- name: Insert test data
|
- name: Insert test data
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -51,7 +56,14 @@
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.rowcount == [2, 1]
|
- result.rowcount == [2, 1]
|
||||||
- result.executed_queries == ['INSERT INTO {{ test_table1 }} VALUES (1), (2)', 'INSERT INTO {{ test_table1 }} VALUES (3)']
|
- result.executed_queries == expected_queries
|
||||||
|
- result.execution_time_ms[0] > 0
|
||||||
|
- result.execution_time_ms[1] > 0
|
||||||
|
vars:
|
||||||
|
expected_queries: [
|
||||||
|
'INSERT INTO {{ test_table1 }} VALUES (1), (2)',
|
||||||
|
'INSERT INTO {{ test_table1 }} VALUES (3)',
|
||||||
|
]
|
||||||
|
|
||||||
- name: Check data in {{ test_table1 }}
|
- name: Check data in {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -64,11 +76,13 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ['SELECT * FROM {{ test_table1 }}']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [3]
|
- result.rowcount == [3]
|
||||||
- result.query_result[0][0].id == 1
|
- result.query_result[0][0].id == 1
|
||||||
- result.query_result[0][1].id == 2
|
- result.query_result[0][1].id == 2
|
||||||
- result.query_result[0][2].id == 3
|
- result.query_result[0][2].id == 3
|
||||||
|
vars:
|
||||||
|
expected_queries: ['SELECT * FROM {{ test_table1 }}']
|
||||||
|
|
||||||
- name: Check data in {{ test_table1 }} using positional args
|
- name: Check data in {{ test_table1 }} using positional args
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -83,9 +97,11 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [1]
|
- result.rowcount == [1]
|
||||||
- result.query_result[0][0].id == 1
|
- result.query_result[0][0].id == 1
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
|
||||||
|
|
||||||
- name: Check data in {{ test_table1 }} using named args
|
- name: Check data in {{ test_table1 }} using named args
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -100,9 +116,11 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [1]
|
- result.rowcount == [1]
|
||||||
- result.query_result[0][0].id == 1
|
- result.query_result[0][0].id == 1
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SELECT * FROM {{ test_table1 }} WHERE id = 1"]
|
||||||
|
|
||||||
- name: Update data in {{ test_table1 }}
|
- name: Update data in {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -118,8 +136,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [1]
|
- result.rowcount == [1]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
|
||||||
|
|
||||||
- name: Check the prev update - row with value 1 does not exist anymore
|
- name: Check the prev update - row with value 1 does not exist anymore
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -134,8 +154,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 1']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [0]
|
- result.rowcount == [0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['SELECT * FROM {{ test_table1 }} WHERE id = 1']
|
||||||
|
|
||||||
- name: Check the prev update - row with value - exist
|
- name: Check the prev update - row with value - exist
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -150,8 +172,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ['SELECT * FROM {{ test_table1 }} WHERE id = 0']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [1]
|
- result.rowcount == [1]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['SELECT * FROM {{ test_table1 }} WHERE id = 0']
|
||||||
|
|
||||||
- name: Update data in {{ test_table1 }} again
|
- name: Update data in {{ test_table1 }} again
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -167,8 +191,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [0]
|
- result.rowcount == [0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['UPDATE {{ test_table1 }} SET id = 0 WHERE id = 1']
|
||||||
|
|
||||||
- name: Delete data from {{ test_table1 }}
|
- name: Delete data from {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -183,8 +209,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [1, 0]
|
- result.rowcount == [1, 0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['DELETE FROM {{ test_table1 }} WHERE id = 0', 'SELECT * FROM {{ test_table1 }} WHERE id = 0']
|
||||||
|
|
||||||
- name: Delete data from {{ test_table1 }} again
|
- name: Delete data from {{ test_table1 }} again
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -197,8 +225,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- result.executed_queries == ['DELETE FROM {{ test_table1 }} WHERE id = 0']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [0]
|
- result.rowcount == [0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['DELETE FROM {{ test_table1 }} WHERE id = 0']
|
||||||
|
|
||||||
- name: Truncate {{ test_table1 }}
|
- name: Truncate {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -213,8 +243,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [0, 0]
|
- result.rowcount == [0, 0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['TRUNCATE {{ test_table1 }}', 'SELECT * FROM {{ test_table1 }}']
|
||||||
|
|
||||||
- name: Rename {{ test_table1 }}
|
- name: Rename {{ test_table1 }}
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -227,8 +259,10 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}']
|
- result.executed_queries == expected_queries
|
||||||
- result.rowcount == [0]
|
- result.rowcount == [0]
|
||||||
|
vars:
|
||||||
|
expected_queries: ['RENAME TABLE {{ test_table1 }} TO {{ test_table2 }}']
|
||||||
|
|
||||||
- name: Check the prev rename
|
- name: Check the prev rename
|
||||||
mysql_query:
|
mysql_query:
|
||||||
|
@ -395,7 +429,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.executed_queries == ['DROP DATABASE {{ test_db }}']
|
- result.executed_queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ['DROP DATABASE {{ test_db }}']
|
||||||
|
|
||||||
always:
|
always:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- vars:
|
||||||
|
mysql_parameters: &mysql_params
|
||||||
|
login_user: '{{ mysql_user }}'
|
||||||
|
login_password: '{{ mysql_password }}'
|
||||||
|
login_host: '{{ mysql_host }}'
|
||||||
|
login_port: '{{ mysql_primary_port }}'
|
||||||
|
block:
|
||||||
|
|
||||||
|
- name: Disable ssl verification
|
||||||
|
community.mysql.mysql_replication:
|
||||||
|
<<: *mysql_params
|
||||||
|
login_port: '{{ mysql_replica1_port }}'
|
||||||
|
mode: changeprimary
|
||||||
|
primary_ssl_verify_server_cert: false
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that changeprimmary is changed and return expected query for MariaDB and MySQL < 8.0.23
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.queries == expected_queries
|
||||||
|
when:
|
||||||
|
- >
|
||||||
|
db_engine == 'mariadb' or
|
||||||
|
(db_engine == 'mysql' and db_version is version('8.0.23', '<'))
|
||||||
|
vars:
|
||||||
|
expected_queries: ["CHANGE MASTER TO MASTER_SSL_VERIFY_SERVER_CERT=0"]
|
||||||
|
|
||||||
|
- name: Assert that changeprimmary is changed and return expected query for MySQL > 8.0.23
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.queries == expected_queries
|
||||||
|
when:
|
||||||
|
- db_engine == 'mysql'
|
||||||
|
- db_version is version('8.0.23', '>=')
|
||||||
|
vars:
|
||||||
|
expected_queries: ["CHANGE REPLICATION SOURCE TO SOURCE_SSL_VERIFY_SERVER_CERT=0"]
|
||||||
|
|
||||||
|
- name: Disable ssl verification for MySQL 8.0.23+
|
||||||
|
community.mysql.mysql_replication:
|
||||||
|
<<: *mysql_params
|
||||||
|
login_port: '{{ mysql_replica1_port }}'
|
||||||
|
mode: changereplication
|
||||||
|
primary_ssl_verify_server_cert: false
|
||||||
|
register: result
|
||||||
|
when:
|
||||||
|
- db_engine == 'mysql'
|
||||||
|
- db_version is version('8.0.23', '>=')
|
||||||
|
|
||||||
|
- name: Assert that changereplication is changed and return expected query for MySQL > 8.0.23
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.queries == expected_queries
|
||||||
|
when:
|
||||||
|
- db_engine == 'mysql'
|
||||||
|
- db_version is version('8.0.23', '>=')
|
||||||
|
vars:
|
||||||
|
expected_queries: ["CHANGE REPLICATION SOURCE TO SOURCE_SSL_VERIFY_SERVER_CERT=0"]
|
|
@ -4,7 +4,7 @@
|
||||||
# and should not be used as examples of how to write Ansible roles #
|
# and should not be used as examples of how to write Ansible roles #
|
||||||
####################################################################
|
####################################################################
|
||||||
|
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# Initial CI tests of mysql_replication module:
|
# Initial CI tests of mysql_replication module:
|
||||||
|
@ -13,6 +13,10 @@
|
||||||
# Tests of replication filters and force_context
|
# Tests of replication filters and force_context
|
||||||
- include_tasks: issue-265.yml
|
- include_tasks: issue-265.yml
|
||||||
|
|
||||||
|
# primary_ssl_verify_server_cert
|
||||||
|
# Must run before mysql add channels in mysql_replication_channel.yml
|
||||||
|
- import_tasks: issue-689.yml
|
||||||
|
|
||||||
# Tests of primary_delay parameter:
|
# Tests of primary_delay parameter:
|
||||||
- import_tasks: mysql_replication_primary_delay.yml
|
- import_tasks: mysql_replication_primary_delay.yml
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
- vars:
|
- vars:
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.queries == result_query or result_query2
|
- result.queries in [result_query, result_query2]
|
||||||
vars:
|
vars:
|
||||||
result_query: ["START SLAVE FOR CHANNEL '{{ test_channel }}'"]
|
result_query: ["START SLAVE FOR CHANNEL '{{ test_channel }}'"]
|
||||||
result_query2: ["START REPLICA FOR CHANNEL '{{ test_channel }}'"]
|
result_query2: ["START REPLICA FOR CHANNEL '{{ test_channel }}'"]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
- vars:
|
- vars:
|
||||||
|
@ -337,5 +337,6 @@
|
||||||
- name: Assert that stopslave returns expected error message
|
- name: Assert that stopslave returns expected error message
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result.msg == "value of mode must be one of{{ ":" }} getprimary, getreplica, changeprimary, stopreplica, startreplica, resetprimary, resetreplica, resetreplicaall, changereplication, got{{ ":" }} stopslave"
|
-
|
||||||
|
"result.msg == 'value of mode must be one of: getprimary, getreplica, changeprimary, stopreplica, startreplica, resetprimary, resetreplica, resetreplicaall, changereplication, got: stopslave'"
|
||||||
- result is failed
|
- result is failed
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
- vars:
|
- vars:
|
||||||
|
@ -55,5 +55,5 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- replica_status.SQL_Delay == {{ test_primary_delay }}
|
- replica_status.SQL_Delay == test_primary_delay
|
||||||
- replica_status is not changed
|
- replica_status is not changed
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
- vars:
|
- vars:
|
||||||
|
|
112
tests/integration/targets/test_mysql_user/tasks/issue-671.yaml
Normal file
112
tests/integration/targets/test_mysql_user/tasks/issue-671.yaml
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
---
|
||||||
|
# Due to https://bugs.mysql.com/bug.php?id=115953, in Mysql 8, if ANSI_QUOTES is enabled,
|
||||||
|
# backticks will be used instead of double quotes to quote functions or procedures name.
|
||||||
|
# As a consequence, mysql_user and mysql_roles will always report "changed" for functions
|
||||||
|
# and procedures no matter the privileges are granted or not.
|
||||||
|
# Workaround for the mysql bug 116953 is removing ANSI_QUOTES from the module's session
|
||||||
|
# sql_mode. But because issue 671, ANSI_QUOTES is always got from GLOBAL sql_mode, thus
|
||||||
|
# this workaround can't work. Even without the Mysql bug, because sql_mode in session
|
||||||
|
# precedes GLOBAL sql_mode. we should check for sql_mode in session variable instead of
|
||||||
|
# the GLOBAL one.
|
||||||
|
- vars:
|
||||||
|
mysql_parameters: &mysql_params
|
||||||
|
login_user: '{{ mysql_user }}'
|
||||||
|
login_password: '{{ mysql_password }}'
|
||||||
|
login_host: '{{ mysql_host }}'
|
||||||
|
login_port: '{{ mysql_primary_port }}'
|
||||||
|
|
||||||
|
block:
|
||||||
|
- name: Issue-671| test setup | drop database
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
|
||||||
|
- name: Issue-671| test setup | create database
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
loop:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
|
||||||
|
- name: Issue-671| test setup | get value of GLOBAL.sql_mode
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query: 'select @@GLOBAL.sql_mode AS sql_mode'
|
||||||
|
register: sql_mode_orig
|
||||||
|
|
||||||
|
- name: Issue-671| Assert sql_mode_orig
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sql_mode_orig.query_result[0][0].sql_mode != None
|
||||||
|
|
||||||
|
- name: Issue-671| enable sql_mode ANSI_QUOTES
|
||||||
|
community.mysql.mysql_variables:
|
||||||
|
<<: *mysql_params
|
||||||
|
variable: sql_mode
|
||||||
|
value: '{{ sql_mode_orig.query_result[0][0].sql_mode }},ANSI_QUOTES'
|
||||||
|
mode: "{% if db_engine == 'mariadb' %}global{% else %}persist{% endif %}"
|
||||||
|
|
||||||
|
- name: Issue-671| Copy SQL scripts to remote
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: "{{ remote_tmp_dir }}/{{ item | basename }}"
|
||||||
|
loop:
|
||||||
|
- create-function.sql
|
||||||
|
- create-procedure.sql
|
||||||
|
|
||||||
|
- name: Issue-671| Create function for test
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: "{{ mysql_command }} < {{ remote_tmp_dir }}/create-function.sql"
|
||||||
|
|
||||||
|
- name: Issue-671| Create procedure for test
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: "{{ mysql_command }} < {{ remote_tmp_dir }}/create-procedure.sql"
|
||||||
|
|
||||||
|
- name: Issue-671| Create user with FUNCTION and PROCEDURE privileges
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: '{{ user_name_2 }}'
|
||||||
|
password: '{{ user_password_2 }}'
|
||||||
|
state: present
|
||||||
|
priv: 'FUNCTION foo.function:EXECUTE/foo.*:SELECT/PROCEDURE bar.procedure:EXECUTE'
|
||||||
|
|
||||||
|
- name: Issue-671| Grant the privileges again, remove ANSI_QUOTES from the session variable
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
session_vars:
|
||||||
|
sql_mode: ""
|
||||||
|
name: '{{ user_name_2 }}'
|
||||||
|
password: '{{ user_password_2 }}'
|
||||||
|
state: present
|
||||||
|
priv: 'FUNCTION foo.function:EXECUTE/foo.*:SELECT/PROCEDURE bar.procedure:EXECUTE'
|
||||||
|
register: result
|
||||||
|
failed_when:
|
||||||
|
- result is failed or result is changed
|
||||||
|
|
||||||
|
- name: Issue-671| Test teardown | cleanup databases
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- foo
|
||||||
|
- bar
|
||||||
|
|
||||||
|
- name: Issue-671| set sql_mode back to original value
|
||||||
|
community.mysql.mysql_variables:
|
||||||
|
<<: *mysql_params
|
||||||
|
variable: sql_mode
|
||||||
|
value: '{{ sql_mode_orig.query_result[0][0].sql_mode }}'
|
||||||
|
mode: "{% if db_engine == 'mariadb' %}global{% else %}persist{% endif %}"
|
||||||
|
|
||||||
|
- name: Issue-671| Teardown user_name_2
|
||||||
|
ansible.builtin.include_tasks:
|
||||||
|
file: utils/remove_user.yml
|
||||||
|
vars:
|
||||||
|
user_name: "{{ user_name_2 }}"
|
|
@ -283,6 +283,12 @@
|
||||||
tags:
|
tags:
|
||||||
- issue-64560
|
- issue-64560
|
||||||
|
|
||||||
|
- name: Test ANSI_QUOTES
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: issue-671.yaml
|
||||||
|
tags:
|
||||||
|
- issue-671
|
||||||
|
|
||||||
# Test that mysql_user still works with force_context enabled (database set to "mysql")
|
# Test that mysql_user still works with force_context enabled (database set to "mysql")
|
||||||
# (https://github.com/ansible-collections/community.mysql/issues/265)
|
# (https://github.com/ansible-collections/community.mysql/issues/265)
|
||||||
- include_tasks: issue-265.yml
|
- include_tasks: issue-265.yml
|
||||||
|
@ -299,3 +305,7 @@
|
||||||
- name: Mysql_user - test update_password
|
- name: Mysql_user - test update_password
|
||||||
ansible.builtin.import_tasks:
|
ansible.builtin.import_tasks:
|
||||||
file: test_update_password.yml
|
file: test_update_password.yml
|
||||||
|
|
||||||
|
- name: Mysql_user - test user_locking
|
||||||
|
ansible.builtin.import_tasks:
|
||||||
|
file: test_user_locking.yml
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
- name: Privs | Assert that 'GRANT' permission is present
|
- name: Privs | Assert that 'GRANT' permission is present
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- mysql_info_about_users.users.localhost.{{ user_name_2 }}.Grant_priv == 'Y'
|
- mysql_info_about_users.users.localhost.db_user2.Grant_priv == 'Y'
|
||||||
|
|
||||||
- name: Privs | Test idempotency (expect ok)
|
- name: Privs | Test idempotency (expect ok)
|
||||||
mysql_user:
|
mysql_user:
|
||||||
|
@ -246,7 +246,7 @@
|
||||||
- name: Privs | Assert that 'GRANT' permission is present (by host)
|
- name: Privs | Assert that 'GRANT' permission is present (by host)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- mysql_info_about_users.users.localhost.{{ user_name_2 }}.Grant_priv == 'Y'
|
- mysql_info_about_users.users.localhost.db_user2.Grant_priv == 'Y'
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
- name: Privs | Update user with invalid privileges
|
- name: Privs | Update user with invalid privileges
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- vars:
|
||||||
|
mysql_parameters: &mysql_params
|
||||||
|
login_user: '{{ mysql_user }}'
|
||||||
|
login_password: '{{ mysql_password }}'
|
||||||
|
login_host: '{{ mysql_host }}'
|
||||||
|
login_port: '{{ mysql_primary_port }}'
|
||||||
|
|
||||||
|
block:
|
||||||
|
|
||||||
|
# ========================= Prepare =======================================
|
||||||
|
- name: Mysql_user Lock user | Create a test database
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_lock_user_test
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# ========================== Tests ========================================
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Create test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
password: 'msandbox'
|
||||||
|
locked: true
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Assert that test user is locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is not search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: 'Mysql_user Lock user | create locked | Idempotence check'
|
||||||
|
check_mode: true
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: true
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
register: idempotence_check
|
||||||
|
failed_when: idempotence_check is changed
|
||||||
|
|
||||||
|
- name: 'Mysql_user Lock user | create locked | Check that absense of locked does not unlock the user'
|
||||||
|
check_mode: true
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
register: idempotence_check
|
||||||
|
failed_when: idempotence_check is changed
|
||||||
|
|
||||||
|
- name: 'Mysql_user Lock user | create locked | Unlock test user check_mode: true'
|
||||||
|
check_mode: true
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: false
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Assert that test user is locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is not search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Unlock test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: false
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Assert that test user is not locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create locked | Remove test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Create test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
password: 'msandbox'
|
||||||
|
locked: false
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Assert that test user is not locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: 'Mysql_user Lock user | create unlocked | Idempotence check'
|
||||||
|
check_mode: true
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: false
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
register: idempotence_check
|
||||||
|
failed_when: idempotence_check is changed
|
||||||
|
|
||||||
|
- name: 'Mysql_user Lock user | create unlocked | Lock test user check_mode: true'
|
||||||
|
check_mode: true
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: true
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Assert that test user is not locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Lock test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
locked: true
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Assert that test user is locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is not search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create unlocked | Remove test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create default | Create test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
password: 'msandbox'
|
||||||
|
priv:
|
||||||
|
'mysql_lock_user_test.*': 'SELECT'
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create default | Assert that test user is not locked
|
||||||
|
community.mysql.mysql_query:
|
||||||
|
<<: *mysql_params
|
||||||
|
query:
|
||||||
|
- SHOW CREATE USER 'mysql_locked_user'@'localhost'
|
||||||
|
register: locked_user_creation
|
||||||
|
failed_when:
|
||||||
|
- locked_user_creation.query_result[0][0] is search('ACCOUNT LOCK')
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | create default | Remove test user
|
||||||
|
community.mysql.mysql_user:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_locked_user
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# ========================= Teardown ======================================
|
||||||
|
|
||||||
|
- name: Mysql_user Lock user | Delete test database
|
||||||
|
community.mysql.mysql_db:
|
||||||
|
<<: *mysql_params
|
||||||
|
name: mysql_lock_user_test
|
||||||
|
state: absent
|
|
@ -45,7 +45,7 @@
|
||||||
- name: Plugin auth | Check that the expected plugin type is set (with hash string)
|
- name: Plugin auth | Check that the expected plugin type is set (with hash string)
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- "'{{ test_plugin_type }}' in show_create_user.stdout"
|
- test_plugin_type in show_create_user.stdout
|
||||||
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
|
when: db_engine == 'mysql' or (db_engine == 'mariadb' and db_version is version('10.3', '>='))
|
||||||
|
|
||||||
- ansible.builtin.include_tasks: utils/assert_user.yml
|
- ansible.builtin.include_tasks: utils/assert_user.yml
|
||||||
|
|
|
@ -17,5 +17,7 @@
|
||||||
- name: Utils | Assert user | Assert user has given privileges
|
- name: Utils | Assert user | Assert user has given privileges
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- "'GRANT {{ priv }} ON *.*' in result.stdout"
|
- expected_command in result.stdout
|
||||||
when: priv is defined
|
when: priv is defined
|
||||||
|
vars:
|
||||||
|
expected_command: "GRANT {{ priv }} ON *.*"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
- name: Assert output message changed value
|
- name: Assert output message changed value
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "output.changed | bool == changed | bool"
|
- output.changed | bool == changed | bool
|
||||||
|
|
||||||
- name: Run mysql command to show variable
|
- name: Run mysql command to show variable
|
||||||
command: "{{ mysql_command }} \"-e show variables like '{{ var_name }}'\""
|
command: "{{ mysql_command }} \"-e show variables like '{{ var_name }}'\""
|
||||||
|
@ -33,5 +33,5 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- "'{{ var_name }}' in result.stdout"
|
- var_name | string in result.stdout
|
||||||
- "'{{ var_value }}' in result.stdout"
|
- var_value | string in result.stdout
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
- name: assert output message changed value
|
- name: assert output message changed value
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "output.changed | bool == changed | bool"
|
- output.changed | bool == changed | bool
|
||||||
|
|
||||||
- set_fact:
|
- set_fact:
|
||||||
key_name: "{{ var_name }}"
|
key_name: "{{ var_name }}"
|
||||||
|
@ -36,5 +36,5 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- "key_name in result.stdout"
|
- key_name in result.stdout
|
||||||
- "key_value in result.stdout"
|
- key_value in result.stdout
|
||||||
|
|
|
@ -92,7 +92,9 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result.queries == ["SET GLOBAL `{{ set_name }}` = {{ set_value }}"]
|
- result.queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SET GLOBAL `{{ set_name }}` = {{ set_value }}"]
|
||||||
|
|
||||||
- include_tasks: assert_var.yml
|
- include_tasks: assert_var.yml
|
||||||
vars:
|
vars:
|
||||||
|
@ -291,9 +293,9 @@
|
||||||
# Bugfix https://github.com/ansible-collections/community.mysql/issues/652
|
# Bugfix https://github.com/ansible-collections/community.mysql/issues/652
|
||||||
|
|
||||||
- name: Get server version
|
- name: Get server version
|
||||||
register: result
|
|
||||||
mysql_info:
|
mysql_info:
|
||||||
<<: *mysql_params
|
<<: *mysql_params
|
||||||
|
register: result
|
||||||
|
|
||||||
- name: Set variable name when running on MySQL
|
- name: Set variable name when running on MySQL
|
||||||
set_fact:
|
set_fact:
|
||||||
|
@ -316,7 +318,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed or result.msg == "Variable is already set to requested value."
|
- result is changed or result.msg == "Variable is already set to requested value."
|
||||||
- result.msg == "Variable is already set to requested value." or result.queries == ["SET GLOBAL `{{ log_slow_statements }}` = ON"]
|
- result.msg == "Variable is already set to requested value." or result.queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SET GLOBAL `{{ log_slow_statements }}` = ON"]
|
||||||
|
|
||||||
- name: Set a boolean value again using ON
|
- name: Set a boolean value again using ON
|
||||||
mysql_variables:
|
mysql_variables:
|
||||||
|
@ -378,7 +382,9 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.queries == ["SET GLOBAL `{{ log_slow_statements }}` = ON"]
|
- result.queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SET GLOBAL `{{ log_slow_statements }}` = ON"]
|
||||||
|
|
||||||
#============================================================
|
#============================================================
|
||||||
# Verify mysql_variable fails with an incorrect login_password parameter
|
# Verify mysql_variable fails with an incorrect login_password parameter
|
||||||
|
@ -452,7 +458,9 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result.queries == ["SET PERSIST `{{ set_name }}` = {{ set_value }}"]
|
- result.queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SET PERSIST `{{ set_name }}` = {{ set_value }}"]
|
||||||
|
|
||||||
- include_tasks: assert_var.yml
|
- include_tasks: assert_var.yml
|
||||||
vars:
|
vars:
|
||||||
|
@ -494,7 +502,9 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result is changed
|
- result is changed
|
||||||
- result.queries == ["SET PERSIST_ONLY `{{ set_name }}` = {{ set_value }}"]
|
- result.queries == expected_queries
|
||||||
|
vars:
|
||||||
|
expected_queries: ["SET PERSIST_ONLY `{{ set_name }}` = {{ set_value }}"]
|
||||||
|
|
||||||
- name: try to update mysql variable value (expect changed=false) in persist_only mode again
|
- name: try to update mysql variable value (expect changed=false) in persist_only mode again
|
||||||
mysql_variables:
|
mysql_variables:
|
||||||
|
|
3
tests/sanity/ignore-2.19.txt
Normal file
3
tests/sanity/ignore-2.19.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
plugins/modules/mysql_db.py validate-modules:use-run-command-not-popen
|
||||||
|
plugins/module_utils/mysql.py pylint:unused-import
|
||||||
|
plugins/module_utils/version.py pylint:unused-import
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
# Copyright: (c) 2020, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue