mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-08-02 20:24:24 -07:00
Merge 9e90a23af8
into 1f9b1a29dd
This commit is contained in:
commit
e4643471bf
9 changed files with 445 additions and 6 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- mysql_replication - add ``startgroupreplication`` and ``stopgroupreplication`` options (https://github.com/ansible-collections/community.mysql/pull/647).
|
|
@ -20,6 +20,7 @@ author:
|
||||||
- Balazs Pocze (@banyek)
|
- Balazs Pocze (@banyek)
|
||||||
- Andrew Klychkov (@Andersson007)
|
- Andrew Klychkov (@Andersson007)
|
||||||
- Dennis Urtubia (@dennisurtubia)
|
- Dennis Urtubia (@dennisurtubia)
|
||||||
|
- Sebastian Pfahl (@eryx12o45)
|
||||||
- Laurent Indermühle (@laurent-indermuehle)
|
- Laurent Indermühle (@laurent-indermuehle)
|
||||||
options:
|
options:
|
||||||
mode:
|
mode:
|
||||||
|
@ -33,7 +34,9 @@ options:
|
||||||
C(stopreplica) (STOP REPLICA),
|
C(stopreplica) (STOP REPLICA),
|
||||||
C(resetprimary) (RESET MASTER) - supported since community.mysql 0.1.0,
|
C(resetprimary) (RESET MASTER) - supported since community.mysql 0.1.0,
|
||||||
C(resetreplica) (RESET REPLICA),
|
C(resetreplica) (RESET REPLICA),
|
||||||
C(resetreplicaall) (RESET REPLICA ALL).
|
C(resetreplicaall) (RESET REPLICA ALL),
|
||||||
|
C(startgroupreplication) (START GROUP_REPLICATION) - supported since community.mysql 3.15.0,
|
||||||
|
C(stopgroupreplication) (STOP GROUP_REPLICATION) - supported since community.mysql 3.15.0.
|
||||||
type: str
|
type: str
|
||||||
choices:
|
choices:
|
||||||
- changeprimary
|
- changeprimary
|
||||||
|
@ -45,6 +48,8 @@ options:
|
||||||
- resetprimary
|
- resetprimary
|
||||||
- resetreplica
|
- resetreplica
|
||||||
- resetreplicaall
|
- resetreplicaall
|
||||||
|
- startgroupreplication
|
||||||
|
- stopgroupreplication
|
||||||
default: getreplica
|
default: getreplica
|
||||||
primary_host:
|
primary_host:
|
||||||
description:
|
description:
|
||||||
|
@ -191,7 +196,16 @@ options:
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
version_added: '0.1.0'
|
version_added: '0.1.0'
|
||||||
|
group_replication_user:
|
||||||
|
description:
|
||||||
|
- User for group replication.
|
||||||
|
type: str
|
||||||
|
version_added: '3.15.0'
|
||||||
|
group_replication_password:
|
||||||
|
description:
|
||||||
|
- Password for group replication user.
|
||||||
|
type: str
|
||||||
|
version_added: '3.15.0'
|
||||||
notes:
|
notes:
|
||||||
- Compatible with MariaDB or MySQL.
|
- Compatible with MariaDB or MySQL.
|
||||||
- If an empty value for the parameter of string type is needed, use an empty string.
|
- If an empty value for the parameter of string type is needed, use an empty string.
|
||||||
|
@ -285,6 +299,17 @@ EXAMPLES = r'''
|
||||||
community.mysql.mysql_replication:
|
community.mysql.mysql_replication:
|
||||||
mode: changeprimary
|
mode: changeprimary
|
||||||
fail_on_error: true
|
fail_on_error: true
|
||||||
|
|
||||||
|
- name: Start mysql group replication
|
||||||
|
community.mysql.mysql_replication:
|
||||||
|
mode: startgroupreplication
|
||||||
|
group_replication_user: group_repl_user
|
||||||
|
group_replication_password: group_repl_passwd
|
||||||
|
|
||||||
|
- name: Stop mysql group replication
|
||||||
|
community.mysql.mysql_replication:
|
||||||
|
mode: stopgroupreplication
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
|
@ -465,6 +490,38 @@ def changereplication(cursor, chm, channel=''):
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
|
||||||
|
|
||||||
|
def startgroupreplication(module, cursor, chm, fail_on_error=False, term='GROUP_REPLICATION'):
|
||||||
|
query = 'START %s %s' % (term, ','.join(chm))
|
||||||
|
|
||||||
|
try:
|
||||||
|
executed_queries.append(query)
|
||||||
|
cursor.execute(query)
|
||||||
|
started = True
|
||||||
|
except mysql_driver.Warning as e:
|
||||||
|
started = False
|
||||||
|
except Exception as e:
|
||||||
|
if fail_on_error:
|
||||||
|
module.fail_json(msg="START %s failed: %s" % (term, to_native(e)))
|
||||||
|
started = False
|
||||||
|
return started
|
||||||
|
|
||||||
|
|
||||||
|
def stopgroupreplication(module, cursor, fail_on_error=False, term='GROUP_REPLICATION'):
|
||||||
|
query = 'STOP %s' % term
|
||||||
|
|
||||||
|
try:
|
||||||
|
executed_queries.append(query)
|
||||||
|
cursor.execute(query)
|
||||||
|
stopped = True
|
||||||
|
except mysql_driver.Warning as e:
|
||||||
|
stopped = False
|
||||||
|
except Exception as e:
|
||||||
|
if fail_on_error:
|
||||||
|
module.fail_json(msg="STOP %s failed: %s" % (term, to_native(e)))
|
||||||
|
stopped = False
|
||||||
|
return stopped
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = mysql_common_argument_spec()
|
argument_spec = mysql_common_argument_spec()
|
||||||
argument_spec.update(
|
argument_spec.update(
|
||||||
|
@ -477,7 +534,9 @@ def main():
|
||||||
'resetprimary',
|
'resetprimary',
|
||||||
'resetreplica',
|
'resetreplica',
|
||||||
'resetreplicaall',
|
'resetreplicaall',
|
||||||
'changereplication']),
|
'changereplication',
|
||||||
|
'startgroupreplication',
|
||||||
|
'stopgroupreplication']),
|
||||||
primary_auto_position=dict(type='bool', default=False, aliases=['master_auto_position']),
|
primary_auto_position=dict(type='bool', default=False, aliases=['master_auto_position']),
|
||||||
primary_host=dict(type='str', aliases=['master_host']),
|
primary_host=dict(type='str', aliases=['master_host']),
|
||||||
primary_user=dict(type='str', aliases=['master_user']),
|
primary_user=dict(type='str', aliases=['master_user']),
|
||||||
|
@ -501,6 +560,8 @@ def main():
|
||||||
connection_name=dict(type='str'),
|
connection_name=dict(type='str'),
|
||||||
channel=dict(type='str'),
|
channel=dict(type='str'),
|
||||||
fail_on_error=dict(type='bool', default=False),
|
fail_on_error=dict(type='bool', default=False),
|
||||||
|
group_replication_user=dict(type='str'),
|
||||||
|
group_replication_password=dict(type='str', no_log=True),
|
||||||
)
|
)
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
|
@ -540,6 +601,8 @@ def main():
|
||||||
connection_name = module.params["connection_name"]
|
connection_name = module.params["connection_name"]
|
||||||
channel = module.params['channel']
|
channel = module.params['channel']
|
||||||
fail_on_error = module.params['fail_on_error']
|
fail_on_error = module.params['fail_on_error']
|
||||||
|
group_replication_user = module.params['group_replication_user']
|
||||||
|
group_replication_password = module.params['group_replication_password']
|
||||||
|
|
||||||
if mysql_driver is None:
|
if mysql_driver is None:
|
||||||
module.fail_json(msg=mysql_driver_fail_msg)
|
module.fail_json(msg=mysql_driver_fail_msg)
|
||||||
|
@ -742,6 +805,24 @@ def main():
|
||||||
module.fail_json(msg='%s. Query == CHANGE REPLICATION SOURCE TO %s' % (to_native(e), chm))
|
module.fail_json(msg='%s. Query == CHANGE REPLICATION SOURCE TO %s' % (to_native(e), chm))
|
||||||
result['changed'] = True
|
result['changed'] = True
|
||||||
module.exit_json(queries=executed_queries, **result)
|
module.exit_json(queries=executed_queries, **result)
|
||||||
|
elif mode == "startgroupreplication":
|
||||||
|
chm = []
|
||||||
|
if group_replication_user is not None:
|
||||||
|
chm.append(" USER='%s'" % group_replication_user)
|
||||||
|
if group_replication_password is not None:
|
||||||
|
chm.append(" PASSWORD='%s'" % group_replication_password)
|
||||||
|
started = startgroupreplication(module, cursor, chm, fail_on_error)
|
||||||
|
if started:
|
||||||
|
module.exit_json(msg="Group replication started ", changed=True, queries=executed_queries)
|
||||||
|
else:
|
||||||
|
module.exit_json(msg="Group replication already started (Or cannot be started)", changed=False,
|
||||||
|
ueries=executed_queries)
|
||||||
|
elif mode == "stopgroupreplication":
|
||||||
|
stopped = stopgroupreplication(module, cursor, channel, fail_on_error)
|
||||||
|
if stopped:
|
||||||
|
module.exit_json(msg="Group replication stopped", changed=True, queries=executed_queries)
|
||||||
|
else:
|
||||||
|
module.exit_json(msg="Group replication already stopped", changed=False, queries=executed_queries)
|
||||||
|
|
||||||
warnings.simplefilter("ignore")
|
warnings.simplefilter("ignore")
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,11 @@ test_channel: test_channel-1
|
||||||
|
|
||||||
user_name_1: 'db_user1'
|
user_name_1: 'db_user1'
|
||||||
user_password_1: 'gadfFDSdtTU^Sdfuj'
|
user_password_1: 'gadfFDSdtTU^Sdfuj'
|
||||||
|
|
||||||
|
enable_group_replication: true
|
||||||
|
group_replication_group_name: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||||
|
group_replication_port: 33061
|
||||||
|
group_replication_user: 'group_repl_user'
|
||||||
|
group_replication_pass: 'group_repl_pass'
|
||||||
|
group_replication_local_address: "{{ mysql_host }}:{{ group_replication_port }}"
|
||||||
|
group_replication_group_seeds: "{{ mysql_host }}:{{ group_replication_port }}"
|
||||||
|
|
|
@ -35,3 +35,9 @@
|
||||||
when:
|
when:
|
||||||
- db_engine == 'mysql'
|
- db_engine == 'mysql'
|
||||||
- db_version is version('8.0.23', '>=')
|
- db_version is version('8.0.23', '>=')
|
||||||
|
|
||||||
|
# Tests of group replication:
|
||||||
|
- import_tasks: mysql_replication_group.yml
|
||||||
|
when:
|
||||||
|
- (db_engine == 'mysql' and db_version is version('8.0.0', '>=')) or
|
||||||
|
(db_engine == 'mariadb' and db_version is version('10.1.0', '>='))
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
---
|
||||||
|
# Copyright: (c) 2025, Sebastian Pfahl (@eryx12o45)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
- vars:
|
||||||
|
mysql_params: &mysql_params
|
||||||
|
login_user: '{{ mysql_user }}'
|
||||||
|
login_password: '{{ mysql_password }}'
|
||||||
|
login_host: '{{ mysql_host }}'
|
||||||
|
|
||||||
|
block:
|
||||||
|
# Setup group replication prerequisites
|
||||||
|
- name: Create group replication user
|
||||||
|
shell:
|
||||||
|
"echo \"CREATE USER IF NOT EXISTS \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}' \
|
||||||
|
IDENTIFIED {% if db_engine == 'mysql' %}WITH mysql_native_password {% endif %}BY '{{ group_replication_pass }}'; \
|
||||||
|
GRANT REPLICATION SLAVE ON *.* TO \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}'; \
|
||||||
|
GRANT CONNECTION_ADMIN ON *.* TO \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}'; \
|
||||||
|
GRANT BACKUP_ADMIN ON *.* TO \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}'; \
|
||||||
|
GRANT GROUP_REPLICATION_STREAM ON *.* TO \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}'; \
|
||||||
|
FLUSH PRIVILEGES;\" | {{ mysql_command }}"
|
||||||
|
when: db_engine == 'mysql' and db_version is version('8.0.0', '>=')
|
||||||
|
|
||||||
|
- name: Create group replication user for MariaDB
|
||||||
|
shell:
|
||||||
|
"echo \"CREATE USER IF NOT EXISTS \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}' \
|
||||||
|
IDENTIFIED BY '{{ group_replication_pass }}'; \
|
||||||
|
GRANT REPLICATION SLAVE ON *.* TO \
|
||||||
|
'{{ group_replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}"
|
||||||
|
when: db_engine == 'mariadb'
|
||||||
|
|
||||||
|
# Configure group replication settings
|
||||||
|
- name: Configure group replication settings for MySQL
|
||||||
|
shell:
|
||||||
|
"echo \"INSTALL PLUGIN group_replication SONAME 'group_replication.so'; \
|
||||||
|
SET GLOBAL group_replication_group_name='{{ group_replication_group_name }}'; \
|
||||||
|
SET GLOBAL group_replication_local_address='{{ mysql_host }}:{{ group_replication_port }}'; \
|
||||||
|
SET GLOBAL group_replication_group_seeds='{{ mysql_host }}:{{ group_replication_port }}'; \
|
||||||
|
SET GLOBAL group_replication_bootstrap_group=ON;\" | {{ mysql_command }}"
|
||||||
|
when: db_engine == 'mysql' and db_version is version('8.0.0', '>=')
|
||||||
|
|
||||||
|
- name: Configure group replication settings for MariaDB
|
||||||
|
shell:
|
||||||
|
"echo \"SET GLOBAL wsrep_provider='/usr/lib/galera/libgalera_smm.so'; \
|
||||||
|
SET GLOBAL wsrep_cluster_name='{{ group_replication_group_name }}'; \
|
||||||
|
SET GLOBAL wsrep_cluster_address='gcomm://{{ mysql_host }}:{{ group_replication_port }}'; \
|
||||||
|
SET GLOBAL wsrep_node_address='{{ mysql_host }}:{{ group_replication_port }}';\" | {{ mysql_command }}"
|
||||||
|
when: db_engine == 'mariadb' and db_version is version('10.1.0', '>=')
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
# Test startgroupreplication mode
|
||||||
|
- name: Start group replication
|
||||||
|
mysql_replication:
|
||||||
|
<<: *mysql_params
|
||||||
|
mode: startgroupreplication
|
||||||
|
group_replication_user: '{{ group_replication_user }}'
|
||||||
|
group_replication_password: '{{ group_replication_pass }}'
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Assert that startgroupreplication returns expected values
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.queries | length > 0
|
||||||
|
- "'START GROUP_REPLICATION' in result.queries[0]"
|
||||||
|
when: result is not failed
|
||||||
|
|
||||||
|
# Check group replication status
|
||||||
|
- name: Check group replication status
|
||||||
|
shell:
|
||||||
|
"echo \"SHOW STATUS LIKE 'group_replication_status';\" | {{ mysql_command }}"
|
||||||
|
register: gr_status
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
# Test stopgroupreplication mode
|
||||||
|
- name: Stop group replication
|
||||||
|
mysql_replication:
|
||||||
|
<<: *mysql_params
|
||||||
|
mode: stopgroupreplication
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Assert that stopgroupreplication returns expected values
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.queries | length > 0
|
||||||
|
- "'STOP GROUP_REPLICATION' in result.queries[0]"
|
||||||
|
when: result is not failed
|
||||||
|
|
||||||
|
# Cleanup group replication settings
|
||||||
|
- name: Reset group replication settings for MySQL
|
||||||
|
shell:
|
||||||
|
"echo \"SET GLOBAL group_replication_bootstrap_group=OFF;\" | {{ mysql_command }}"
|
||||||
|
when: db_engine == 'mysql' and db_version is version('8.0.0', '>=')
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Drop group replication user
|
||||||
|
shell:
|
||||||
|
"echo \"DROP USER IF EXISTS '{{ group_replication_user }}'@'{{ mysql_host }}';\" | {{ mysql_command }}"
|
||||||
|
ignore_errors: true
|
|
@ -338,5 +338,5 @@
|
||||||
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, startgroupreplication, stopgroupreplication, got: stopslave'"
|
||||||
- result is failed
|
- result is failed
|
||||||
|
|
|
@ -7,7 +7,7 @@ __metaclass__ = type
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ansible_collections.community.mysql.plugins.module_utils.implementations.mariadb.replication import uses_replica_terminology
|
from ansible_collections.community.mysql.plugins.module_utils.implementations.mariadb.replication import uses_replica_terminology
|
||||||
from ..utils import dummy_cursor_class
|
from ..utils import dummy_cursor_class, MockCursor
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -22,3 +22,108 @@ from ..utils import dummy_cursor_class
|
||||||
def test_uses_replica_terminology(f_output, c_output, c_ret_type):
|
def test_uses_replica_terminology(f_output, c_output, c_ret_type):
|
||||||
cursor = dummy_cursor_class(c_output, c_ret_type)
|
cursor = dummy_cursor_class(c_output, c_ret_type)
|
||||||
assert uses_replica_terminology(cursor) == f_output
|
assert uses_replica_terminology(cursor) == f_output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'user,password,expected_query',
|
||||||
|
[
|
||||||
|
(None, None, "START GROUP_REPLICATION "),
|
||||||
|
("repl_user", None, "START GROUP_REPLICATION USER='repl_user'"),
|
||||||
|
(None, "repl_pass", "START GROUP_REPLICATION PASSWORD='repl_pass'"),
|
||||||
|
("repl_user", "repl_pass", "START GROUP_REPLICATION USER='repl_user',PASSWORD='repl_pass'"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_start_group_replication(user, password, expected_query):
|
||||||
|
"""Test startgroupreplication function with different parameters."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import startgroupreplication
|
||||||
|
|
||||||
|
cursor = MockCursor()
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
chm = []
|
||||||
|
if user:
|
||||||
|
chm.append("USER='%s'" % user)
|
||||||
|
if password:
|
||||||
|
chm.append("PASSWORD='%s'" % password)
|
||||||
|
|
||||||
|
result = startgroupreplication(module, cursor, chm, False)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
assert cursor.executed_queries[0] == expected_query
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_group_replication():
|
||||||
|
"""Test stopgroupreplication function."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import stopgroupreplication
|
||||||
|
|
||||||
|
cursor = MockCursor()
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = stopgroupreplication(module, cursor, False)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
assert cursor.executed_queries[0] == "STOP GROUP_REPLICATION"
|
||||||
|
|
||||||
|
|
||||||
|
def test_start_group_replication_fail():
|
||||||
|
"""Test startgroupreplication function with failure."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import startgroupreplication
|
||||||
|
from ..utils import MockWarning
|
||||||
|
|
||||||
|
# Create a mock mysql_driver with a Warning attribute
|
||||||
|
class MockDriver:
|
||||||
|
Warning = MockWarning
|
||||||
|
|
||||||
|
# Save the original mysql_driver
|
||||||
|
from ansible_collections.community.mysql.plugins.modules import mysql_replication
|
||||||
|
original_driver = mysql_replication.mysql_driver
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Replace with our mock driver
|
||||||
|
mysql_replication.mysql_driver = MockDriver
|
||||||
|
|
||||||
|
cursor = MockCursor(status="ERROR")
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = startgroupreplication(module, cursor, [], True)
|
||||||
|
|
||||||
|
assert result is False
|
||||||
|
finally:
|
||||||
|
# Restore the original driver
|
||||||
|
mysql_replication.mysql_driver = original_driver
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_group_replication_fail():
|
||||||
|
"""Test stopgroupreplication function with failure."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import stopgroupreplication
|
||||||
|
from ..utils import MockWarning
|
||||||
|
|
||||||
|
# Create a mock mysql_driver with a Warning attribute
|
||||||
|
class MockDriver:
|
||||||
|
Warning = MockWarning
|
||||||
|
|
||||||
|
# Save the original mysql_driver
|
||||||
|
from ansible_collections.community.mysql.plugins.modules import mysql_replication
|
||||||
|
original_driver = mysql_replication.mysql_driver
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Replace with our mock driver
|
||||||
|
mysql_replication.mysql_driver = MockDriver
|
||||||
|
|
||||||
|
cursor = MockCursor(status="ERROR")
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = stopgroupreplication(module, cursor, True)
|
||||||
|
|
||||||
|
assert result is False
|
||||||
|
finally:
|
||||||
|
# Restore the original driver
|
||||||
|
mysql_replication.mysql_driver = original_driver
|
||||||
|
|
|
@ -7,7 +7,7 @@ __metaclass__ = type
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ansible_collections.community.mysql.plugins.module_utils.implementations.mysql.replication import uses_replica_terminology
|
from ansible_collections.community.mysql.plugins.module_utils.implementations.mysql.replication import uses_replica_terminology
|
||||||
from ..utils import dummy_cursor_class
|
from ..utils import dummy_cursor_class, MockCursor
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -26,3 +26,108 @@ from ..utils import dummy_cursor_class
|
||||||
def test_uses_replica_terminology(f_output, c_output, c_ret_type):
|
def test_uses_replica_terminology(f_output, c_output, c_ret_type):
|
||||||
cursor = dummy_cursor_class(c_output, c_ret_type)
|
cursor = dummy_cursor_class(c_output, c_ret_type)
|
||||||
assert uses_replica_terminology(cursor) == f_output
|
assert uses_replica_terminology(cursor) == f_output
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'user,password,expected_query',
|
||||||
|
[
|
||||||
|
(None, None, "START GROUP_REPLICATION "),
|
||||||
|
("repl_user", None, "START GROUP_REPLICATION USER='repl_user'"),
|
||||||
|
(None, "repl_pass", "START GROUP_REPLICATION PASSWORD='repl_pass'"),
|
||||||
|
("repl_user", "repl_pass", "START GROUP_REPLICATION USER='repl_user',PASSWORD='repl_pass'"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_start_group_replication(user, password, expected_query):
|
||||||
|
"""Test startgroupreplication function with different parameters."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import startgroupreplication
|
||||||
|
|
||||||
|
cursor = MockCursor()
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
chm = []
|
||||||
|
if user:
|
||||||
|
chm.append("USER='%s'" % user)
|
||||||
|
if password:
|
||||||
|
chm.append("PASSWORD='%s'" % password)
|
||||||
|
|
||||||
|
result = startgroupreplication(module, cursor, chm, False)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
assert cursor.executed_queries[0] == expected_query
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_group_replication():
|
||||||
|
"""Test stopgroupreplication function."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import stopgroupreplication
|
||||||
|
|
||||||
|
cursor = MockCursor()
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = stopgroupreplication(module, cursor, False)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
assert cursor.executed_queries[0] == "STOP GROUP_REPLICATION"
|
||||||
|
|
||||||
|
|
||||||
|
def test_start_group_replication_fail():
|
||||||
|
"""Test startgroupreplication function with failure."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import startgroupreplication
|
||||||
|
from ..utils import MockWarning
|
||||||
|
|
||||||
|
# Create a mock mysql_driver with a Warning attribute
|
||||||
|
class MockDriver:
|
||||||
|
Warning = MockWarning
|
||||||
|
|
||||||
|
# Save the original mysql_driver
|
||||||
|
from ansible_collections.community.mysql.plugins.modules import mysql_replication
|
||||||
|
original_driver = mysql_replication.mysql_driver
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Replace with our mock driver
|
||||||
|
mysql_replication.mysql_driver = MockDriver
|
||||||
|
|
||||||
|
cursor = MockCursor(status="ERROR")
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = startgroupreplication(module, cursor, [], True)
|
||||||
|
|
||||||
|
assert result is False
|
||||||
|
finally:
|
||||||
|
# Restore the original driver
|
||||||
|
mysql_replication.mysql_driver = original_driver
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_group_replication_fail():
|
||||||
|
"""Test stopgroupreplication function with failure."""
|
||||||
|
from ansible_collections.community.mysql.plugins.modules.mysql_replication import stopgroupreplication
|
||||||
|
from ..utils import MockWarning
|
||||||
|
|
||||||
|
# Create a mock mysql_driver with a Warning attribute
|
||||||
|
class MockDriver:
|
||||||
|
Warning = MockWarning
|
||||||
|
|
||||||
|
# Save the original mysql_driver
|
||||||
|
from ansible_collections.community.mysql.plugins.modules import mysql_replication
|
||||||
|
original_driver = mysql_replication.mysql_driver
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Replace with our mock driver
|
||||||
|
mysql_replication.mysql_driver = MockDriver
|
||||||
|
|
||||||
|
cursor = MockCursor(status="ERROR")
|
||||||
|
module = type('obj', (object,), {
|
||||||
|
'fail_json': lambda msg: None,
|
||||||
|
})
|
||||||
|
|
||||||
|
result = stopgroupreplication(module, cursor, True)
|
||||||
|
|
||||||
|
assert result is False
|
||||||
|
finally:
|
||||||
|
# Restore the original driver
|
||||||
|
mysql_replication.mysql_driver = original_driver
|
||||||
|
|
|
@ -17,3 +17,27 @@ class dummy_cursor_class():
|
||||||
|
|
||||||
elif self.ret_val_type == 'list':
|
elif self.ret_val_type == 'list':
|
||||||
return [self.output]
|
return [self.output]
|
||||||
|
|
||||||
|
|
||||||
|
# Define MockWarning at module level to ensure it's a proper exception class
|
||||||
|
class MockWarning(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MockCursor:
|
||||||
|
# Set the Warning class at the class level
|
||||||
|
Warning = MockWarning
|
||||||
|
|
||||||
|
def __init__(self, status="ONLINE"):
|
||||||
|
self.status = status
|
||||||
|
self.executed_queries = []
|
||||||
|
|
||||||
|
def execute(self, query):
|
||||||
|
self.executed_queries.append(query)
|
||||||
|
if self.status == "ERROR":
|
||||||
|
raise MockWarning("Mocked execution error")
|
||||||
|
|
||||||
|
def fetchone(self):
|
||||||
|
if len(self.executed_queries) > 0 and "group_replication_status" in self.executed_queries[-1]:
|
||||||
|
return ["group_replication_status", self.status]
|
||||||
|
return None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue