Last active
September 6, 2023 08:00
-
-
Save OrangeDog/49871e06b017318b7498b810e2ad7caa to your computer and use it in GitHub Desktop.
Stateful DDL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Need to bypass module loader in order to access private functions | |
from salt.modules import postgres | |
def __init__(opts): | |
postgres.__grains__ = __grains__ | |
postgres.__opts__ = opts | |
postgres.__salt__ = __salt__ | |
def _kwargs(kwargs): | |
""" | |
Used to forward common arguments for postgres module | |
""" | |
return {k: v for k, v in kwargs.items() if k in ( | |
'user', 'host', 'port', 'maintenance_db', 'password', 'runas')} | |
def apply_script(dbname, source, source_hash, transaction=True, **kwargs): | |
owner = kwargs.get('runas', 'postgres') | |
tmp_filename = __utils__['files.mkstemp']() | |
comment = "COMMENT ON DATABASE %s IS '%s'" % (dbname, source_hash) | |
args = ['--set', 'ON_ERROR_STOP=1', | |
'--echo-all', | |
'--file', tmp_filename, | |
'--command', comment] | |
if transaction: | |
args.append('--single-transaction') | |
try: | |
cp_kwargs = {k: v for k, v in kwargs.items() | |
if k in ('template', 'saltenv')} | |
cp_ret = __salt__['cp.get_template'](source, tmp_filename, **cp_kwargs) | |
if cp_ret != tmp_filename: | |
return False | |
__salt__['file.chown'](tmp_filename, owner, owner) | |
psql_ret = postgres._psql_prepare_and_run(args, maintenance_db=dbname, | |
**_kwargs(kwargs)) | |
return psql_ret['retcode'] == 0 | |
finally: | |
__utils__['files.remove'](tmp_filename) | |
def get_database_comment(name, **kwargs): | |
sql = "SELECT description FROM pg_shdescription " \ | |
"JOIN pg_database ON objoid = pg_database.oid " \ | |
"WHERE datname = '%s'" % name | |
rows = __salt__['postgres.psql_query'](sql, **_kwargs(kwargs)) | |
return rows[0]['description'] if rows else None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def apply(name, source, source_hash=None, transaction=True, **kwargs): | |
""" | |
Manage versioning of DDL using a script and a database comment. | |
The DDL script must be applicable to any previous state, i.e. it must | |
use ``CREATE IF EXISTS`` and ``ALTER`` statements. | |
External changes to database schema will not trigger this to run. | |
.. warning:: | |
The hash is of the source file, so any templating must be stateless. | |
:param name: Name of database to which to apply the script | |
:param source: Source of the script (see ``file.present``) | |
:param source_hash: Override hash used for versioning | |
:param transaction: Whether the script should be run within a transaction | |
""" | |
ret = {'name': name, 'changes': {}, 'comment': ''} | |
if source_hash is None: | |
source_hash = __salt__['cp.hash_file'](source, saltenv=__env__)['hsum'] | |
comment = __salt__['pg_ddl.get_database_comment'](name, **kwargs) | |
if source_hash == comment: | |
ret['comment'] = 'Script is already applied to %s' % name | |
ret['result'] = True | |
return ret | |
ret['changes'].update({'old': comment, 'new': source_hash}) | |
if __opts__['test']: | |
ret['comment'] = 'Script would be applied to %s' % name | |
ret['result'] = None | |
return ret | |
ret['result'] = __salt__['pg_ddl.apply_script'](name, source, source_hash, | |
transaction=transaction, | |
saltenv=__env__, | |
**kwargs) | |
if ret['result']: | |
ret['comment'] = 'Script applied to %s' % name | |
else: | |
ret['comment'] = 'Failed to apply script to %s' % name | |
return ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment