add basic backup, backup-list and restore functionality

This commit is contained in:
kjeld Schouten-Lebbing 2022-01-19 22:15:29 +01:00
parent 779b632835
commit fdd76bbce5
No known key found for this signature in database
GPG Key ID: 4CDAD4A532BC1EDB
3 changed files with 118 additions and 47 deletions

View File

@ -14,16 +14,30 @@ run `pip install --upgrade truetool`
## How to use ## How to use
Just run `truetool` in the shell of your TrueNAS SCALE machine, to have it process Patch and Minor version updates for all Apps running `truetool` should be a good start.
Additional options are available: Additional options are available:
- `truetool --catalog CATALOGNAME` where CATALOGNAME is the name of the catalog you want to process in caps ##### Help
- `truetool --versioning SCHEME` where SCHEME is the highest semver version you want to process. options: `patch`, `minor` and `major`
- `truetool -h` for the CLI help page - `truetool -h` for the CLI help page
- `truetool -s` or ` truetool --sync` to sync the catalogs before running auto-update
- `truetool -p` or ` truetool --prune` to prune (remove) old docker images after running auto-update
##### Update
- `truetool -u` or ` truetool --update` update TrueNAS SCALE Apps
- `truetool --catalog CATALOGNAME` where CATALOGNAME is the name of the catalog you want to process in caps
- `truetool --versioning SCHEME` where SCHEME is the highest semver version you want to process. options: `patch`, `minor` and `major`
- `truetool -a` or ` truetool --all` updates both active (running) and non-active (stuck or stopped) Apps - `truetool -a` or ` truetool --all` updates both active (running) and non-active (stuck or stopped) Apps
#### Backup
- `truetool -b` or ` truetool --backup` backup the complete Apps system prior to updates - `truetool -b` or ` truetool --backup` backup the complete Apps system prior to updates
- `truetool -r` or ` truetool --restore` restores a specific backup by name
#### Other
- `truetool -s` or ` truetool --sync` to sync the catalogs before running updates
- `truetool -p` or ` truetool --prune` to prune (remove) old docker images after running auto-update

View File

@ -7,7 +7,7 @@ README_MD = open(join(dirname(abspath(__file__)), "README.md")).read()
setup( setup(
name="truetool", name="truetool",
version="1.0.0", version="2.0.0",
# The packages that constitute your project. # The packages that constitute your project.
# For my project, I have only one - "pydash". # For my project, I have only one - "pydash".

View File

@ -2,6 +2,7 @@ import subprocess
import sys import sys
import argparse import argparse
import time import time
from datetime import datetime
class Chart(object): class Chart(object):
def __setattr__(self, name, value): def __setattr__(self, name, value):
@ -51,6 +52,7 @@ def check_semver(current: str, latest: str):
def execute_upgrades(): def execute_upgrades():
if UPDATE:
if ALL: if ALL:
if CATALOG == "ALL": if CATALOG == "ALL":
filtered = filter(lambda a: a.update_available and a.status == "active", INSTALLED_CHARTS) filtered = filter(lambda a: a.update_available and a.status == "active", INSTALLED_CHARTS)
@ -77,6 +79,8 @@ def execute_upgrades():
print(f"{chart.name} failed to upgrade. \n{result.stdout.decode('utf-8')}") print(f"{chart.name} failed to upgrade. \n{result.stdout.decode('utf-8')}")
else: else:
print(f"{chart.name} upgraded ({pre_update_ver} --> {post_update_ver})") print(f"{chart.name} upgraded ({pre_update_ver} --> {post_update_ver})")
else:
print("Update disabled, skipping...")
def fetch_charts(): def fetch_charts():
rawcharts = subprocess.run(["cli", "-c", "app chart_release query"], stdout=subprocess.PIPE) rawcharts = subprocess.run(["cli", "-c", "app chart_release query"], stdout=subprocess.PIPE)
@ -90,16 +94,27 @@ def process_args():
global PRUNE global PRUNE
global ALL global ALL
global BACKUP global BACKUP
global UPDATE
global RESTORE
global LIST
parser = argparse.ArgumentParser(description='Update TrueNAS SCALE Apps') parser = argparse.ArgumentParser(description='Update TrueNAS SCALE Apps')
parser.add_argument('--catalog', nargs='?', default='ALL', help='name of the catalog you want to process in caps. Or "ALL" to render all catalogs.') parser.add_argument('-c', '--catalog', nargs='?', default='ALL', help='name of the catalog you want to process in caps. Or "ALL" to render all catalogs.')
parser.add_argument('--versioning', nargs='?', default='minor', help='Name of the versioning scheme you want to update. Options: major, minor or patch. Defaults to minor') parser.add_argument('-v', '--versioning', nargs='?', default='minor', help='Name of the versioning scheme you want to update. Options: major, minor or patch. Defaults to minor')
parser.add_argument('-s', '--sync', action="store_true", help='sync catalogs before trying to update') parser.add_argument('-s', '--sync', action="store_true", help='sync catalogs before trying to update')
parser.add_argument('-u', '--update', action="store_true", help='update the Apps in the selected catalog')
parser.add_argument('-p', '--prune', action="store_true", help='prune old docker images after update') parser.add_argument('-p', '--prune', action="store_true", help='prune old docker images after update')
parser.add_argument('-a', '--all', action="store_true", help='update "active" apps only and ignore "stopped" or "stuck" apps') parser.add_argument('-a', '--all', action="store_true", help='update "active" apps only and ignore "stopped" or "stuck" apps')
parser.add_argument('-b', '--backup', action="store_true", help='backup the complete Apps system prior to updates') parser.add_argument('-b', '--backup', action="store_true", help='backup the complete Apps system prior to updates')
parser.add_argument('-r', '--restore', nargs='?', help='restore a previous backup, disables all other features')
parser.add_argument('-l', '--list', action="store_true", help='lists existing backups')
args = parser.parse_args() args = parser.parse_args()
CATALOG = args.catalog CATALOG = args.catalog
VERSIONING = args.versioning VERSIONING = args.versioning
RESTORE = args.restore
if args.update:
UPDATE = True
else:
UPDATE = False
if args.sync: if args.sync:
SYNC = True SYNC = True
else: else:
@ -116,6 +131,11 @@ def process_args():
BACKUP = True BACKUP = True
else: else:
BACKUP = False BACKUP = False
if args.list:
LIST = True
else:
LIST = False
def sync_catalog(): def sync_catalog():
if SYNC: if SYNC:
@ -127,17 +147,36 @@ def sync_catalog():
temp = process.stdout.read() temp = process.stdout.read()
if temp: if temp:
print (temp.decode('utf-8')) print (temp.decode('utf-8'))
else:
print("Catalog Sync disabled, skipping...")
def docker_prune(): def docker_prune():
if PRUNE: if PRUNE:
print("Pruning old docker images...\n") print("Pruning old docker images...\n")
process = subprocess.Popen(["docker", "image", "prune", "-af"], stdout=subprocess.PIPE) process = subprocess.Popen(["docker", "image", "prune", "-af"], stdout=subprocess.PIPE)
print("Images pruned.\n") print("Images pruned.\n")
else:
print("Container Image Pruning disabled, skipping...")
def chart_backup(): def apps_backup():
if BACKUP: if BACKUP:
print("Running App Backup...\n") print("Running App Backup...\n")
process = subprocess.Popen(["cli", "-c", "app kubernetes backup_chart_releases"], stdout=subprocess.PIPE) now = datetime.now()
command = "app kubernetes backup_chart_releases backup_name=TrueTool_"+now.strftime("%Y_%d_%m_%H_%M_%S")
process = subprocess.Popen(["cli", "-c", command], stdout=subprocess.PIPE)
while process.poll() is None:
lines = process.stdout.readline()
print (lines.decode('utf-8'))
temp = process.stdout.read()
if temp:
print (temp.decode('utf-8'))
else:
print("Backup disabled, skipping...")
def backups_list():
if LIST:
print("Running App Backup...\n")
process = subprocess.Popen(["cli", "-c", "app kubernetes list_backups"], stdout=subprocess.PIPE)
while process.poll() is None: while process.poll() is None:
lines = process.stdout.readline() lines = process.stdout.readline()
print (lines.decode('utf-8')) print (lines.decode('utf-8'))
@ -145,17 +184,35 @@ def chart_backup():
if temp: if temp:
print (temp.decode('utf-8')) print (temp.decode('utf-8'))
def apps_restore():
print("Running Backup Restore...\n")
command = "app kubernetes restore_backup backup_name="+RESTORE
print(f"{command}")
process = subprocess.Popen(["cli", "-c", command], stdout=subprocess.PIPE)
while process.poll() is None:
lines = process.stdout.readline()
print (lines.decode('utf-8'))
temp = process.stdout.read()
if temp:
print (temp.decode('utf-8'))
def run(): def run():
process_args() process_args()
print("Starting TrueCharts App updater...\n") print("Starting TrueCharts TrueTool...\n")
chart_backup() if RESTORE:
apps_restore()
elif LIST:
backups_list()
else:
apps_backup()
sync_catalog() sync_catalog()
charts = fetch_charts() charts = fetch_charts()
parse_charts(charts) parse_charts(charts)
print("Executing Updates...\n") print("Executing Updates...\n")
execute_upgrades() execute_upgrades()
print("Updating Finished\n")
docker_prune() docker_prune()
print("TrueTool Finished\n")
exit(0) exit(0)