Commit befcd677 authored by Tim Bleimehl's avatar Tim Bleimehl 🤸🏼
Browse files

wip

parent 54d9834d
......@@ -151,5 +151,6 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
mysql_backups
backups
mysql_backups/
backups/
.git/
......@@ -572,10 +572,41 @@ def auto_create_kubernetes(namespace, all_namespaces):
click.echo(f"Created {count_dbs} database(s) in {count_db_instances} instance(s)")
@auto_create.command(name="docker")
def auto_create_docker():
# you are here. maybe we dont new "now" command and instead a kubernetes and a docker version
from container_helper import ContainerHelper
count_db_instances = 0
count_dbs = 0
for container in ContainerHelper.docker_get_container_to_be_backed_up():
count_db_instances += 1
if container.coda_labels[ValidLabels.enabled].val:
BackupperClass = database_type_backupper_mapping[
container.coda_labels[ValidLabels.database_type].val
]
bu: BaseBackupper = BackupperClass(container)
created_dbs = bu.auto_create()
if created_dbs:
count_dbs += len(created_dbs)
click.echo(f"Created {count_dbs} database(s) in {count_db_instances} instance(s)")
@cli_root.command(name="list-labels")
def list_labels():
print("")
click.echo(ValidLabels.list_labels_human_readable())
@click.option(
"--output-format",
"-o",
default="human",
help="Define the output format: 'human' an easy to read table, 'json' or 'yaml' for inter-process readability, dict if used in a python script",
type=click.Choice(["human", "json", "yaml", "dict"], case_sensitive=False),
)
def list_labels(output_format):
output = ValidLabels.list_labels(output_format)
click.echo(output)
return output
if __name__ == "__main__":
......
......@@ -172,7 +172,7 @@ class ContainerHelper:
raise NotImplementedError(
f"Can not query pods of workload. Unknown workload format. Expected to find keys 'spec.selector.matchLabels' in Workload. got \n\n{workload}\n\n"
)
pod_selector_labels: List[Label] = Label.from_dict(
pod_selector_labels: List[Label] = Label.dict_to_label(
workload["spec"]["selector"]["matchLabels"]
)
for wl_pod in cls.kubernetes_get_pods(
......
from distutils import util
from typing import List, Dict, Type, Any, Union
import json
import yaml
import copy
import logging
......@@ -46,12 +48,24 @@ class Label:
self.info: str = info
@classmethod
def from_dict(cls, labels: dict) -> List["Label"]:
def dict_to_label(cls, labels: dict) -> List["Label"]:
l = []
for key, val in labels.items():
l.append(Label({key: val}))
return l
def to_dict(self, hide_val: bool = False) -> Dict:
lbl_dict = {
"key": self.key,
"type": self.type.__name__,
"possible_values": self.possible_values,
"default": self.default,
"info": self.info,
}
if not hide_val:
lbl_dict["value"] = self.val
return lbl_dict
def __eq__(self, other: Union["Label", str]):
return (
type(other) is type(self)
......@@ -279,16 +293,32 @@ class ValidLabels:
return lbls
@classmethod
def list_labels_human_readable(cls):
# ToDo: make this better readable for humans
s = ""
for label in cls.iter():
s += f"\n{label.key} \n"
s += f" type: {label.type.__name__}\n"
if label.default is not None:
s += f" default: {label.default}\n"
if label.possible_values:
s += f" possible_values: {label.possible_values}\n"
if label.info:
s += f" {label.info}\n"
return s
def list_labels(cls, format: str = "human"):
if format == "human":
# ToDo: make this better readable for humans
s = ""
for label in cls.iter():
s += f"\n# {label.key} \n"
s += f"\ttype: {label.type.__name__}\n"
if label.default is not None:
s += f"\tdefault: {label.default}\n"
if label.possible_values:
s += f"\tpossible_values: {label.possible_values}\n"
if label.info:
s += f" {label.info}\n"
return s
elif format in ["yaml", "json", "dict"]:
lbls = []
for label in cls.iter():
lbls.append(label.to_dict(hide_val=True))
if format == "yaml":
return yaml.dump(lbls)
elif format == "json":
return json.dumps(lbls)
else:
return lbls
else:
raise ValueError(
"Expected format to be on of ['human','json','yaml','dict'] got '{format}'"
)
......@@ -26,4 +26,4 @@ if __name__ == "__main__":
mysql.retention.rotate_existing_backups()
# mysql.restore("redcado","mysqlbackup_2021-12-29_14-19-40")
"""
print(ValidLabels.list_labels_human_readable())
print(ValidLabels.list_labels())
......@@ -4,7 +4,7 @@ A container native database backup and restore solution
Maintainer: tim.bleimehl@dzd-ev.de
Status: Alpha (WIP - not basic-feature completed yet)
Status: Alpha (WIP - **do not use productive yet**)
# What is this (short)
......@@ -78,17 +78,15 @@ Thats it. We now have a directory `./backups/` in front of us, with all database
* Automatic backup retentation management (Daily, Weekly, Monthly, Yearly)
* "Backup now!" wizard
* Compressed backup
* Auto create databases and users
# Planned features
* (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) Email notification
* (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) 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/) (needs a metadata store :/ )
......@@ -97,6 +95,7 @@ Thats it. We now have a directory `./backups/` in front of us, with all database
* (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
* (Idea) Improve human readable output by printing a tree structure (https://www.baeldung.com/java-print-binary-tree-diagram)
# Current ToDo
* implement RETENTION_ON_COLLISION_KEEP_NEWEST_BACKUP
......
......@@ -7,17 +7,19 @@ COPY --from=docker:latest /usr/local/bin/docker /usr/local/bin/
# install python3
RUN install_packages python3 python3-pip
# install required python modules
COPY reqs.txt /tmp/reqs.txt
RUN pip3 install --no-cache-dir -r /tmp/reqs.txt
RUN pip3 install setuptools
# copy backupper python scripts
COPY . /opt/CoDaBackup
RUN pip3 install -e /opt/CoDaBackup
# Switch back to non root user
#USER 1001
# copy backupper python scripts
COPY sqlbackupper /opt/sqlbackupper
# Set config to "DOCKER"-Profile (see config.py)
ENV CONFIGS_BACKUP_DIR="/backups"
# Volume for backup dir
VOLUME ["/backup"]
ENTRYPOINT [ "/opt/sqlbackupper/cli.py" ]
ENTRYPOINT [ "/opt/CoDaBackup/CoDaBackup/cli.py" ]
CMD [ "--help" ]
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment