f"Can not parse '{ValidLabels.auto_create_databases.key}'-Label. Valid format is json list of obects. got {self.container.coda_labels[ValidLabels.auto_create_databases]}"
# example value for to_exist_db: 'mydb/myuser/supersavepassw,otherdb/otheruser/savepw'
db_props:List=to_exist_db.split("/")
iflen(db_props)==3:
database_name,user_name,user_password=db_props
eliflen(db_props)==1:
database_name=db_props[0]
database_name=None
user_name=None
user_password=None
if"database"into_exist_db:
database_name=to_exist_db["database"].lower()
else:
raiseValueError(
f"Unexpected format in {ValidLabels.auto_create_databases.key}. Got '{to_be_existing_databases_data}'.\nLabel help:{ValidLabels.auto_create_databases.info}"
f"Expeted property 'database' in auto-create config object in label{ValidLabels.auto_create_databases.key}. got '{to_exist_db}'"
)
if"user"into_exist_db:
user_name=to_exist_db["user"].lower()
if"password"into_exist_db:
user_password=to_exist_db["password"]
ifnotuser_name:
user_name=self.user
user_password=self.password
# clean input data
database_name=database_name.strip()
user_name=user_name.strip()
user_password=user_password.strip()
# lets go
touched_user_or_database:bool=False
ifnotuser_nameinexisting_users:
# user does not exists. lets create it
log.info(f"Create user '{user_name}'@'{self.container.name}' ")
@@ -308,14 +341,14 @@ class MySQLBackupper(BaseBackupper):
defget_create_database_command(
self,
database_name,
enabled_user_name,
encoding,
collation,
executive_db_user_name=None,
executive_db_user_pw=None,
):
# character set UTF8mb4 collate utf8mb4_bin
returnf"""{self.bin_cmd} -N -h{self.host} -u{executive_db_user_nameifexecutive_db_user_nameelseself.user} -p{executive_db_user_pwifexecutive_db_user_nameelseself.password} -e "CREATE DATABASE `{database_name}` {"CHARACTER SET = '"+encoding+"'"ifencodingelse""}{"COLLATE = '"+collation+"'"ifcollationelse""}; GRANT ALL privileges ON `{database_name}`.* TO '{enabled_user_name}'@'%';FLUSH PRIVILEGES;" """
returnf"""{command_base} "CREATE DATABASE {database_name}{"CHARACTER SET = '"+encoding+"'"ifencodingelse""}{"COLLATE = '"+collation+"'"ifcollationelse""};" """
defget_create_user_command(
self,
...
...
@@ -324,9 +357,21 @@ class MySQLBackupper(BaseBackupper):
executive_db_user_name=None,
executive_db_user_pw=None,
):
log.warning("Create mysql user with not network restrictions (`@'%'`)")
log.warning("Create mysql user with no network restrictions (@'%')")
returnf"""{self.bin_cmd} -N -h{self.host} -u{executive_db_user_nameifexecutive_db_user_nameelseself.user} -p{executive_db_user_pwifexecutive_db_user_nameelseself.password} -e "CREATE USER '{username}'@'%' IDENTIFIED BY '{password}';" """
defget_grant_access_to_user_command(
self,
username,
database,
executive_db_user_name=None,
executive_db_user_pw=None,
):
log.warning(
f"Grant access to '{database}' for user '{username}' with no network restrictions (@'%')"
)
returnf"""{self.bin_cmd} -N -h{self.host} -u{executive_db_user_nameifexecutive_db_user_nameelseself.user} -p{executive_db_user_pwifexecutive_db_user_nameelseself.password} -e "GRANT ALL privileges ON {database}.* TO '{username}'@'%';FLUSH PRIVILEGES;" """
classPostgresBackupper(BaseBackupper):
bin_dump:str="/usr/bin/pg_dump"
...
...
@@ -358,13 +403,15 @@ class PostgresBackupper(BaseBackupper):
defget_create_database_command(
self,
database_name,
enabled_user_name,
encoding,
collation,
executive_db_user_name=None,
executive_db_user_pw=None,
):
returnf"""env PGPASSWORD={executive_db_user_pwifexecutive_db_user_nameelseself.password}{self.bin_cmd} -U {executive_db_user_nameifexecutive_db_user_nameelseself.user} -h {self.host} -t -c "CREATE DATABASE {database_name}{"ENCODING '"+encoding+"'"ifencodingelse''}{"LC_COLLATE = '"+collation+"'"ifcollationelse''}; GRANT ALL PRIVILEGES ON DATABASE {database_name} TO {enabled_user_name};" """
@@ -84,20 +84,19 @@ Thats it. We now have a directory `./backups/` in front of us, with all database
* (WIP) Restore Wizard
* (WIP) Neo4j support
* (WIP) Auto database creation if not exists
* (WIP) Create database if not existent via label conf (checked/executed when pod starts via https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/)
* (Planned) Database auth via Docker/kubernetes Secrets
* (Planned) Create database if not existent via label conf (checked/executed when pod starts via https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/)
* (Planned) Email notification
* (Planned) Support of docker and kubernetes secrets for providing database auth
* (Planned) Docker Event listener / Kubectl hooks to react to container started/stopped
* (Planned) Improve human readable output by printing a tree structure (https://www.baeldung.com/java-print-binary-tree-diagram)
* (Planned) Compression optional
* (Idea) Database tools (Create non existing databases, based on labels)
* (Planned) Backup compression optional
* (Idea) Switch to https://github.com/kubernetes-client/python and https://docker-py.readthedocs.io/en/stable/ (or create alternative modules)
* (Idea) restore by label (checked/executed when pod starts via https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/)
* (Idea) restore by label (checked/executed when pod starts via https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/) (needs a metadata store :/ )
* (Idea) Matrix notifications
* (Idea) [Podman](https://podman.io/) support. Your help is greatly appreciated. Should be easy or maybe no work at all
* (Idea) [LCX](https://linuxcontainers.org/) support. Help needed!
* (Idea) Suppord pod with more than one container https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/#opening-a-shell-when-a-pod-has-more-than-one-container
* (Idea) Provide auto-create params in https://kubernetes.io/docs/concepts/configuration/configmap/ instead of k8s annotation