Viewing file: charmed_postgresql.py (6.05 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# This file is part of the sos project: https://github.com/sosreport/sos # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # version 2 of the GNU General Public License. # # See the LICENSE file in the source distribution for further information.
import os import yaml
from sos.report.plugins import Plugin, UbuntuPlugin
SNAP_COMMON_PATH = "/var/snap/charmed-postgresql/common" SNAP_CURRENT_PATH = "/var/snap/charmed-postgresql/current"
PATHS = { "POSTGRESQL_CONF": SNAP_COMMON_PATH + "/var/lib/postgresql", "POSTGRESQL_LOGS": SNAP_COMMON_PATH + "/var/log/postgresql", "PATRONI_CONF": SNAP_CURRENT_PATH + "/etc/patroni", "PATRONI_LOGS": SNAP_COMMON_PATH + "/var/log/patroni", "PGBACKREST_CONF": SNAP_CURRENT_PATH + "/etc/pgbackrest", "PGBACKREST_LOGS": SNAP_COMMON_PATH + "/var/log/pgbackrest", "PGBOUNCER_CONF": SNAP_CURRENT_PATH + "/etc/pgbouncer", "PGBOUNCER_LOGS": SNAP_COMMON_PATH + "/var/log/pgbouncer", }
PATRONI_CONFIG_FILE = f"{PATHS['PATRONI_CONF']}/patroni.yaml"
RUNAS = "snap_daemon" PSQL = "charmed-postgresql.psql" PATRONICTL = "charmed-postgresql.patronictl"
class CharmedPostgreSQL(Plugin, UbuntuPlugin):
short_desc = "Charmed PostgreSQL" plugin_name = "charmed_postgresql" packages = ('charmed-postgresql',)
@property def patronictl_args(self) -> str: return f"--config-file {PATRONI_CONFIG_FILE}"
@property def psql_args(self) -> str: return (f"-U {self.postgresql_username} " f"-h {self.postgresql_host} " f"-p {self.postgresql_port} " r"-d postgres -P pager=off")
def setup(self): # --- FILE EXCLUSIONS ---
# Keys and certificates self.add_forbidden_path([ f"{PATHS['PATRONI_CONF']}/*.pem", f"{PATHS['PGBOUNCER_CONF']}/*.pem", ])
# --- FILE INCLUSIONS ---
self.add_copy_spec([ f"{PATHS['POSTGRESQL_CONF']}/*.conf*", f"{PATHS['POSTGRESQL_LOGS']}", f"{PATHS['PATRONI_CONF']}/*.y*ml", f"{PATHS['PATRONI_LOGS']}", f"{PATHS['PGBACKREST_CONF']}", f"{PATHS['PGBACKREST_LOGS']}", f"{PATHS['PGBOUNCER_CONF']}", f"{PATHS['PGBOUNCER_LOGS']}", ])
# --- SNAP LOGS ---
self.add_journal("snap.charmed-postgresql.*")
# --- SNAP INFO ---
self.add_cmd_output( "snap info charmed-postgresql", suggest_filename="snap-info", )
# Read and parse patroni config, finish setup if there are errors try: with open(PATRONI_CONFIG_FILE, encoding='utf-8') as f: patroni_config = yaml.safe_load(f) self.patroni_cluster_name = patroni_config["scope"] postgresql = patroni_config["postgresql"] host_port = postgresql["connect_address"].split(":") self.postgresql_host, self.postgresql_port = host_port authentication = postgresql["authentication"] superuser = authentication["superuser"] self.postgresql_username = superuser["username"] self.postgresql_password = superuser["password"] except (OSError, yaml.YAMLError, TypeError, ValueError, KeyError, AttributeError) as error: self._log_warn("Can not run additional commands due to " "an error on opening or parsing the config file " f"{PATRONI_CONFIG_FILE}: " f'{error}') return
# --- TOPOLOGY ---
self.add_cmd_output( (f"{PATRONICTL} {self.patronictl_args} " f"topology {self.patroni_cluster_name}"), suggest_filename="patroni-topology", runas=RUNAS, )
# --- HISTORY ---
self.add_cmd_output( (f"{PATRONICTL} {self.patronictl_args} " f"history {self.patroni_cluster_name}"), suggest_filename="patroni-history", runas=RUNAS, )
# --- DCS CONFIGS ---
self.add_cmd_output( (f"{PATRONICTL} {self.patronictl_args} " f"show-config {self.patroni_cluster_name}"), suggest_filename="patroni-dcs-config", runas=RUNAS, )
# ADD DB PASSWORD TO ENVIRONMENT os.environ["PGPASSWORD"] = self.postgresql_password
# --- DATABASES ---
self.add_cmd_output( (f"{PSQL} {self.psql_args} " r"-c '\l+'"), suggest_filename="postgresql-databases", runas=RUNAS, )
# --- USERS ---
self.add_cmd_output( (f"{PSQL} {self.psql_args} " r"-c '\duS+'"), suggest_filename="postgresql-users", runas=RUNAS, )
# --- TABLES ---
self.add_cmd_output( (f"{PSQL} {self.psql_args} " r"-c '\dtS+'"), suggest_filename="postgresql-tables", runas=RUNAS, )
def postproc(self):
# REMOVE DB PASSWORD FROM ENVIRONMENT if "PGPASSWORD" in os.environ: del os.environ["PGPASSWORD"]
# --- SCRUB PASSWORDS ---
# Match lines containing password: and # followed by anything which may be enclosed with " self.do_path_regex_sub( f"{PATHS['PATRONI_CONF']}/*", r'(password: )"?.*"?', r'\1"*********"', )
# https://pgbackrest.org/configuration.html#section-repository/option-repo-s3-key # https://pgbackrest.org/configuration.html#section-repository/option-repo-s3-key-secret self.do_path_regex_sub( f"{PATHS['PGBACKREST_CONF']}/pgbackrest.conf", r'(.*s3-key.*=).*', r'\1*********', )
# https://www.pgbouncer.org/config.html#authentication-file-format self.do_path_regex_sub( f"{PATHS['PGBOUNCER_CONF']}/pgbouncer/userlist.txt", r'(".*" )".*"', r'\1"*********"', )
|