From 9af667a78aef99ff89d4f1783683c717c6d03b57 Mon Sep 17 00:00:00 2001 From: Aleksandr Vagachev Date: Mon, 26 Feb 2024 11:35:06 +0300 Subject: [PATCH] Renaming databases (#43) * clickhouse_db: new arguments added * Add integration tests --- changelogs/fragments/2-clickhouse_db.yml | 4 + plugins/modules/clickhouse_db.py | 73 +++++++++++++++++-- .../targets/clickhouse_db/tasks/initial.yml | 68 +++++++++++++++++ 3 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/2-clickhouse_db.yml diff --git a/changelogs/fragments/2-clickhouse_db.yml b/changelogs/fragments/2-clickhouse_db.yml new file mode 100644 index 0000000..ca49d86 --- /dev/null +++ b/changelogs/fragments/2-clickhouse_db.yml @@ -0,0 +1,4 @@ +minor_changes: +- clickhouse_db - added the ability to rename databases. +- clickhouse_db - add the ``cluster`` argument to execute commands on all cluster hosts. +- clickhouse_db - add the ``target`` argument to rename the database. \ No newline at end of file diff --git a/plugins/modules/clickhouse_db.py b/plugins/modules/clickhouse_db.py index 0bfc3d1..2efc203 100644 --- a/plugins/modules/clickhouse_db.py +++ b/plugins/modules/clickhouse_db.py @@ -26,6 +26,7 @@ author: - Andrew Klychkov (@Andersson007) + - Aleksandr Vagachev (@aleksvagachev) extends_documentation_fragment: - community.clickhouse.client_inst_opts @@ -36,8 +37,9 @@ - Database state. - If C(present), will create the database if not exists. - If C(absent), will drop the database if exists. + - If C(rename), will rename the database if exists. type: str - choices: ['present', 'absent'] + choices: ['present', 'absent', 'rename'] default: 'present' name: description: @@ -48,6 +50,17 @@ description: - Database engine. Once set, cannot be changed. type: str + cluster: + description: + - Run the command on all cluster hosts. + - If the cluster is not configured, the command will crash with an error. + type: str + version_added: '0.4.0' + target: + description: + - Name for renaming the database. + type: str + version_added: '0.4.0' comment: description: - Database comment. Once set, cannot be changed. @@ -75,6 +88,22 @@ login_password: my_password name: test_db state: absent + +# Rename the database test_db to prod_db. +# If the database test_db exists, it will be renamed to prod_db. +# If the database test_db does not exist and the prod_db database exists, +# the module will report that nothing has changed. +# If both the databases exist, an error will be raised. +- name: Rename database + community.clickhouse.clickhouse_db: + login_host: localhost + login_user: alice + login_db: foo + login_password: my_password + name: test_db + target: prod_db + cluster: test_cluster + state: rename ''' RETURN = r''' @@ -102,10 +131,11 @@ class ClickHouseDB(): - def __init__(self, module, client, name): + def __init__(self, module, client, name, cluster): self.module = module self.client = client self.name = name + self.cluster = cluster self.srv_version = get_server_version(self.module, self.client) # Set default values, then update self.exists = False @@ -141,6 +171,9 @@ def create(self, engine, comment): if engine: query += " ENGINE = %s" % engine + if self.cluster: + query += " ON CLUSTER %s" % self.cluster + if comment: query += " COMMENT '%s'" % comment @@ -174,8 +207,23 @@ def update(self, engine, comment): return False + def rename(self, target): + query = "RENAME DATABASE %s TO %s" % (self.name, target) + if self.cluster: + query += " ON CLUSTER %s" % self.cluster + + executed_statements.append(query) + + if not self.module.check_mode: + execute_query(self.module, self.client, query) + + return True + def drop(self): query = "DROP DATABASE %s" % self.name + if self.cluster: + query += " ON CLUSTER %s" % self.cluster + executed_statements.append(query) if not self.module.check_mode: @@ -191,9 +239,11 @@ def main(): # and invoke here to return a dict with those arguments argument_spec = client_common_argument_spec() argument_spec.update( - state=dict(type='str', choices=['present', 'absent'], default='present'), + state=dict(type='str', choices=['present', 'absent', 'rename'], default='present'), name=dict(type='str', required=True), engine=dict(type='str', default=None), + cluster=dict(type='str', default=None), + target=dict(type='str', default=None), comment=dict(type='str', default=None), ) @@ -213,6 +263,8 @@ def main(): state = module.params['state'] name = module.params['name'] engine = module.params['engine'] + cluster = module.params['cluster'] + target = module.params['target'] comment = module.params['comment'] # Will fail if no driver informing the user @@ -223,7 +275,7 @@ def main(): # Do the job changed = False - database = ClickHouseDB(module, client, name) + database = ClickHouseDB(module, client, name, cluster) if comment and database.srv_version['year'] < 22: msg = ('The module supports the comment feature for ClickHouse ' @@ -237,7 +289,18 @@ def main(): else: # If database exists changed = database.update(engine, comment) - + elif state == 'rename': + if database.exists: + changed = database.rename(target) + else: + target_db = ClickHouseDB(module, client, target, cluster) + if target_db.exists: + changed = False + msg = "There is nothing to rename" + module.warn(msg) + else: + msg = "The %s and %s databases do not exist" % (name, target) + module.fail_json(msg=msg) else: # If state is absent if database.exists: diff --git a/tests/integration/targets/clickhouse_db/tasks/initial.yml b/tests/integration/targets/clickhouse_db/tasks/initial.yml index 0fc7166..4f20529 100644 --- a/tests/integration/targets/clickhouse_db/tasks/initial.yml +++ b/tests/integration/targets/clickhouse_db/tasks/initial.yml @@ -223,6 +223,74 @@ - result is not changed - result.executed_statements == [] +# Test rename database +- name: Create database for renaming + register: result + community.clickhouse.clickhouse_db: + name: test_rename_db + +- name: Rename database + register: result + community.clickhouse.clickhouse_db: + name: test_rename_db + target: dev_db + state: rename + +- name: Check ret values + ansible.builtin.assert: + that: + - result is changed + - result.executed_statements == ["RENAME DATABASE test_rename_db TO dev_db"] + +# Test +- name: Rename database in check mode + register: result + check_mode: true + community.clickhouse.clickhouse_db: + state: rename + name: dev_db + target: test_rename_db + +- name: Check ret values + ansible.builtin.assert: + that: + - result is changed + - result.executed_statements == ["RENAME DATABASE dev_db TO test_rename_db"] + +# Test rename database if there is nothing to rename +- name: Rename database if there is nothing to rename + register: result + community.clickhouse.clickhouse_db: + name: test_rename_db + target: dev_db + state: rename + +- name: Check ret values + ansible.builtin.assert: + that: + - result is not changed + - result.executed_statements == [] + - result.warnings != [] + +# Test rename database if both databases exist +- name: Create database for renaming + register: result + community.clickhouse.clickhouse_db: + name: test_rename_db + +- name: Rename database if both databases exist + register: result + community.clickhouse.clickhouse_db: + name: test_rename_db + target: dev_db + state: rename + ignore_errors: true + +- name: Check ret values + ansible.builtin.assert: + that: + - result is failed + # Get srv version for the following block - name: Get server version register: server_info