allow empty user for kerberos ticket usage

fix syntax problems:
* it is possible that sql injection is done, therefore the [DBNAME] syntax is used.
* it is not possible to use default escape on cursor.execute for DBNAME, since it will insert single quotes around the name and this will cause syntax problems / single quotes within the actual DBNAME

implement autocommit setting, since some content can not be imported within transaction

fix for automatic tests

fix problems with named instances, corrected error message regarding configuration file

remove unused placeholder
pull/18777/head
Hans-Joachim Kliemeck 9 years ago committed by Matt Clay
parent 80a77ea00a
commit e43e572770

@ -26,7 +26,7 @@ module: mssql_db
short_description: Add or remove MSSQL databases from a remote host. short_description: Add or remove MSSQL databases from a remote host.
description: description:
- Add or remove MSSQL databases from a remote host. - Add or remove MSSQL databases from a remote host.
version_added: "2.1" version_added: "2.2"
options: options:
name: name:
description: description:
@ -64,6 +64,12 @@ options:
- Location, on the remote host, of the dump file to read from or write to. Uncompressed SQL - Location, on the remote host, of the dump file to read from or write to. Uncompressed SQL
files (C(.sql)) files are supported. files (C(.sql)) files are supported.
required: false required: false
autocommit:
description:
- Automatically commit the change only if the import succeed. Sometimes it is necessary to use autocommit=true, since some content can't be changed within a transaction.
required: false
default: false
choices: [ "false", "true" ]
notes: notes:
- Requires the pymssql Python package on the remote host. For Ubuntu, this - Requires the pymssql Python package on the remote host. For Ubuntu, this
is as easy as pip install pymssql (See M(pip).) is as easy as pip install pymssql (See M(pip).)
@ -79,6 +85,10 @@ EXAMPLES = '''
- mssql_db: name=my_db state=import target=/tmp/dump.sql - mssql_db: name=my_db state=import target=/tmp/dump.sql
''' '''
RETURN = '''
#
'''
import os import os
try: try:
import pymssql import pymssql
@ -89,44 +99,41 @@ else:
def db_exists(conn, cursor, db): def db_exists(conn, cursor, db):
cursor.execute("SELECT name FROM master.sys.databases WHERE name = N'%s'", db) cursor.execute("SELECT name FROM master.sys.databases WHERE name = %s", db)
conn.commit() conn.commit()
return bool(cursor.rowcount) return bool(cursor.rowcount)
def db_create(conn, cursor, db): def db_create(conn, cursor, db):
conn.autocommit(True) cursor.execute("CREATE DATABASE [%s]" % db)
cursor.execute("CREATE DATABASE %s", db)
conn.autocommit(False)
return db_exists(conn, cursor, db) return db_exists(conn, cursor, db)
def db_delete(conn, cursor, db): def db_delete(conn, cursor, db):
conn.autocommit(True)
try: try:
single_user = "alter database %s set single_user with rollback immediate" % db cursor.execute("ALTER DATABASE [%s] SET single_user WITH ROLLBACK IMMEDIATE" % db)
cursor.execute(single_user)
except: except:
pass pass
cursor.execute("DROP DATABASE %s", db) cursor.execute("DROP DATABASE [%s]" % db)
conn.autocommit(False)
return not db_exists(conn, cursor, db) return not db_exists(conn, cursor, db)
def db_import(conn, cursor, module, db, target): def db_import(conn, cursor, module, db, target):
if os.path.isfile(target): if os.path.isfile(target):
with open(target, 'r') as backup: backup = open(target, 'r')
sqlQuery = "USE %s\n" try:
sqlQuery = "USE [%s]\n" % db
for line in backup: for line in backup:
if line is None: if line is None:
break break
elif line.startswith('GO'): elif line.startswith('GO'):
cursor.execute(sqlQuery, db) cursor.execute(sqlQuery)
sqlQuery = "USE %s\n" sqlQuery = "USE [%s]\n" % db
else: else:
sqlQuery += line sqlQuery += line
cursor.execute(sqlQuery, db) cursor.execute(sqlQuery)
conn.commit() conn.commit()
finally:
backup.close()
return 0, "import successful", "" return 0, "import successful", ""
else: else:
return 1, "cannot find target file", "cannot find target file" return 1, "cannot find target file", "cannot find target file"
@ -136,11 +143,12 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
name=dict(required=True, aliases=['db']), name=dict(required=True, aliases=['db']),
login_user=dict(required=True), login_user=dict(default=''),
login_password=dict(required=True), login_password=dict(default=''),
login_host=dict(required=True), login_host=dict(required=True),
login_port=dict(default="1433"), login_port=dict(default='1433'),
target=dict(default=None), target=dict(default=None),
autocommit=dict(type='bool', default=False),
state=dict( state=dict(
default='present', choices=['present', 'absent', 'import']) default='present', choices=['present', 'absent', 'import'])
) )
@ -151,16 +159,20 @@ def main():
db = module.params['name'] db = module.params['name']
state = module.params['state'] state = module.params['state']
autocommit = module.params['autocommit']
target = module.params["target"] target = module.params["target"]
login_user = module.params['login_user'] login_user = module.params['login_user']
login_password = module.params['login_password'] login_password = module.params['login_password']
login_host = module.params['login_host'] login_host = module.params['login_host']
login_port = module.params['login_port'] login_port = module.params['login_port']
login_querystring = "%s:%s" % (login_host, login_port)
login_querystring = login_host
if login_port != "1433":
login_querystring = "%s:%s" % (login_host, login_port)
if login_password is None or login_user is None: if login_user != "" and login_password == "":
module.fail_json(msg="when supplying login arguments, both login_user and login_password must be provided") module.fail_json(msg="when supplying login_user arguments login_password must be provided")
try: try:
conn = pymssql.connect(user=login_user, password=login_password, host=login_querystring, database='master') conn = pymssql.connect(user=login_user, password=login_password, host=login_querystring, database='master')
@ -170,9 +182,11 @@ def main():
errno, errstr = e.args errno, errstr = e.args
module.fail_json(msg="ERROR: %s %s" % (errno, errstr)) module.fail_json(msg="ERROR: %s %s" % (errno, errstr))
else: else:
module.fail_json(msg="unable to connect, check login_user and login_password are correct, or alternatively check ~/.my.cnf contains credentials") module.fail_json(msg="unable to connect, check login_user and login_password are correct, or alternatively check your @sysconfdir@/freetds.conf / ${HOME}/.freetds.conf")
conn.autocommit(True)
changed = False changed = False
if db_exists(conn, cursor, db): if db_exists(conn, cursor, db):
if state == "absent": if state == "absent":
try: try:
@ -180,7 +194,9 @@ def main():
except Exception, e: except Exception, e:
module.fail_json(msg="error deleting database: " + str(e)) module.fail_json(msg="error deleting database: " + str(e))
elif state == "import": elif state == "import":
conn.autocommit(autocommit)
rc, stdout, stderr = db_import(conn, cursor, module, db, target) rc, stdout, stderr = db_import(conn, cursor, module, db, target)
if rc != 0: if rc != 0:
module.fail_json(msg="%s" % stderr) module.fail_json(msg="%s" % stderr)
else: else:
@ -196,7 +212,10 @@ def main():
changed = db_create(conn, cursor, db) changed = db_create(conn, cursor, db)
except Exception, e: except Exception, e:
module.fail_json(msg="error creating database: " + str(e)) module.fail_json(msg="error creating database: " + str(e))
conn.autocommit(autocommit)
rc, stdout, stderr = db_import(conn, cursor, module, db, target) rc, stdout, stderr = db_import(conn, cursor, module, db, target)
if rc != 0: if rc != 0:
module.fail_json(msg="%s" % stderr) module.fail_json(msg="%s" % stderr)
else: else:

Loading…
Cancel
Save