"""Retrieve Pillar data by doing a MySQL queryMariaDB provides Python support through the MySQL Python package.Therefore, you may use this module with both MySQL or MariaDB.This module is a concrete implementation of the sql_base ext_pillar for MySQL.:maturity: new:depends: python-mysqldb:platform: allConfiguring the mysql ext_pillar================================Use the 'mysql' key under ext_pillar for configuration of queries.MySQL configuration of the MySQL returner is being used (mysql.db, mysql.user,mysql.pass, mysql.port, mysql.host) for database connection info.Required python modules: MySQLdbComplete example================.. code-block:: yaml mysql: user: 'salt' pass: 'super_secret_password' db: 'salt_db' port: 3306 ssl: cert: /etc/mysql/client-cert.pem key: /etc/mysql/client-key.pem ext_pillar: - mysql: fromdb: query: 'SELECT col1,col2,col3,col4,col5,col6,col7 FROM some_random_table WHERE minion_pattern LIKE %s' depth: 5 as_list: True with_lists: [1,3]"""importloggingfromcontextlibimportcontextmanagerfromsalt.pillar.sql_baseimportSqlBaseExtPillar# Set up logginglog=logging.getLogger(__name__)try:# Trying to import MySQLdbimportMySQLdbimportMySQLdb.convertersimportMySQLdb.cursorsexceptImportError:try:# MySQLdb import failed, try to import PyMySQLimportpymysqlpymysql.install_as_MySQLdb()importMySQLdbimportMySQLdb.convertersimportMySQLdb.cursorsexceptImportError:MySQLdb=None
[docs]def__virtual__():""" Confirm that a python mysql client is installed. """returnbool(MySQLdb),"No python mysql client installed."ifMySQLdbisNoneelse""
[docs]classMySQLExtPillar(SqlBaseExtPillar):""" This class receives and processes the database rows from MySQL. """@classmethoddef_db_name(cls):return"MySQL"def_get_options(self):""" Returns options used for the MySQL connection. """defaults={"host":"localhost","user":"salt","pass":"salt","db":"salt","port":3306,"ssl":{},}_options={}_opts=__opts__.get("mysql",{})forattr,defaultindefaults.items():ifattrnotin_opts:log.debug("Using default for MySQL %s",attr)_options[attr]=defaultcontinue_options[attr]=_opts[attr]return_options@contextmanagerdef_get_cursor(self):""" Yield a MySQL cursor """_options=self._get_options()conn=MySQLdb.connect(host=_options["host"],user=_options["user"],passwd=_options["pass"],db=_options["db"],port=_options["port"],ssl=_options["ssl"],)cursor=conn.cursor()try:yieldcursorexceptMySQLdb.DatabaseErroraserr:log.exception("Error in ext_pillar MySQL: %s",err.args)finally:conn.close()
[docs]defextract_queries(self,args,kwargs):# pylint: disable=useless-super-delegation""" This function normalizes the config block into a set of queries we can use. The return is a list of consistently laid out dicts. """returnsuper().extract_queries(args,kwargs)
[docs]defext_pillar(minion_id,pillar,*args,**kwargs):""" Execute queries against MySQL, merge and return as a dict """returnMySQLExtPillar().fetch(minion_id,pillar,*args,**kwargs)