Add new --stdin-from-command functionnality

This commit is contained in:
deajan 2024-09-02 00:23:59 +02:00
parent 415c4fe334
commit 5060d280ca
6 changed files with 90 additions and 26 deletions

View file

@ -7,7 +7,7 @@ __intname__ = "npbackup.configuration"
__author__ = "Orsiris de Jong"
__copyright__ = "Copyright (C) 2022-2024 NetInvent"
__license__ = "GPL-3.0-only"
__build__ = "2024061701"
__build__ = "2024090101"
__version__ = "npbackup 3.0.0+"
MIN_CONF_VERSION = 3.0
@ -153,6 +153,7 @@ empty_config_dict = {
"backup_opts": {
"paths": [],
"source_type": None,
"stdin_from_command": None,
"tags": [],
"compression": "auto",
"use_fs_snapshot": True,

View file

@ -1011,9 +1011,10 @@ class NPBackupRunner:
"""
# Possible warnings to add to json output
warnings = []
# Preflight checks
if not read_from_stdin:
stdin_from_command = self.repo_config.g("backup_opts.stdin_from_command")
if not read_from_stdin and not stdin_from_command:
# Preflight checks
paths = self.repo_config.g("backup_opts.paths")
if not paths:
msg = (
@ -1112,7 +1113,17 @@ class NPBackupRunner:
self.restic_runner.verbose = self.verbose
# Run backup here
if not read_from_stdin:
if stdin_from_command:
self.write_logs(
f"Running backup of given command stdout as name {stdin_filename} to repo {self.repo_config.g('name')}",
level="info"
)
elif stdin_filename:
self.write_logs(
f"Running backup of piped stdin data as name {stdin_filename} to repo {self.repo_config.g('name')}",
level="info",
)
else:
if source_type not in ["folder_list", None]:
self.write_logs(
f"Running backup of files in {paths} list to repo {self.repo_config.g('name')}",
@ -1123,11 +1134,6 @@ class NPBackupRunner:
f"Running backup of {paths} to repo {self.repo_config.g('name')}",
level="info",
)
else:
self.write_logs(
f"Running backup of piped stdin data as name {stdin_filename} to repo {self.repo_config.g('name')}",
level="info",
)
pre_exec_commands_success = True
if pre_exec_commands:
@ -1149,7 +1155,21 @@ class NPBackupRunner:
level="info",
)
if not read_from_stdin:
if read_from_stdin:
result = self.restic_runner.backup(
read_from_stdin=read_from_stdin,
stdin_filename=stdin_filename,
tags=tags,
additional_backup_only_parameters=additional_backup_only_parameters,
)
elif stdin_from_command:
result = self.restic_runner.backup(
stdin_from_command=stdin_from_command,
stdin_filename=stdin_filename,
tags=tags,
additional_backup_only_parameters=additional_backup_only_parameters,
)
else:
result = self.restic_runner.backup(
paths=paths,
source_type=source_type,
@ -1163,13 +1183,6 @@ class NPBackupRunner:
tags=tags,
additional_backup_only_parameters=additional_backup_only_parameters,
)
else:
result = self.restic_runner.backup(
read_from_stdin=read_from_stdin,
stdin_filename=stdin_filename,
tags=tags,
additional_backup_only_parameters=additional_backup_only_parameters,
)
self.write_logs(
f"Restic output:\n{self.restic_runner.backup_result_content}", level="debug"

View file

@ -100,6 +100,7 @@ def config_gui(full_config: dict, config_file: str):
"files_from": _t("config_gui.files_from"),
"files_from_verbatim": _t("config_gui.files_from_verbatim"),
"files_from_raw": _t("config_gui.files_from_raw"),
"stdin_from_command": _t("config_gui.stdin_from_command"),
},
"backup_opts.priority": {
"low": _t("config_gui.low"),
@ -847,6 +848,7 @@ def config_gui(full_config: dict, config_file: str):
list(combo_boxes["backup_opts.source_type"].values()),
key="backup_opts.source_type",
size=(48, 1),
enable_events=True,
),
],
[
@ -859,12 +861,24 @@ def config_gui(full_config: dict, config_file: str):
expand_y=True,
)
],
[
sg.Text(_t("config_gui.stdin_from_command"))
],
[
sg.Image(
NON_INHERITED_ICON,
key="inherited.backup_opts.stdin_from_command",
tooltip=_t("config_gui.group_inherited"),
pad=1,
),
sg.Input(key="backup_opts.stdin_from_command", size=(100, 1)),
],
[
sg.Input(visible=False, key="--ADD-PATHS-FILE--", enable_events=True),
sg.FilesBrowse(_t("generic.add_files"), target="--ADD-PATHS-FILE--"),
sg.FilesBrowse(_t("generic.add_files"), target="--ADD-PATHS-FILE--", key="--ADD-PATHS-FILE-BUTTON--"),
sg.Input(visible=False, key="--ADD-PATHS-FOLDER--", enable_events=True),
sg.FolderBrowse(
_t("generic.add_folder"), target="--ADD-PATHS-FOLDER--"
_t("generic.add_folder"), target="--ADD-PATHS-FOLDER--", key="--ADD-PATHS-FOLDER-BUTTON--"
),
sg.Button(_t("generic.add_manually"), key="--ADD-PATHS-MANUALLY--"),
sg.Button(_t("generic.remove_selected"), key="--REMOVE-PATHS--"),
@ -2098,6 +2112,30 @@ Google Cloud storage: GOOGLE_PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS\n\
)
update_global_gui(full_config, unencrypted=False)
continue
if event == "backup_opts.source_type":
value = get_key_from_value(combo_boxes["backup_opts.source_type"], values["backup_opts.source_type"])
if value == "stdin_from_command":
window["backup_opts.paths"].update(visible=False)
window["--ADD-PATHS-FILE-BUTTON--"].update(disabled=True)
window["--ADD-PATHS-FOLDER-BUTTON--"].update(disabled=True)
window["--ADD-PATHS-MANUALLY--"].update(disabled=True)
window["--REMOVE-PATHS--"].update(disabled=True)
window["backup_opts.stdin_from_command"].update(disabled=False)
elif value == "folder_list":
window["backup_opts.paths"].update(visible=True)
window["--ADD-PATHS-FILE-BUTTON--"].update(disabled=False)
window["--ADD-PATHS-FOLDER-BUTTON--"].update(disabled=False)
window["--ADD-PATHS-MANUALLY--"].update(disabled=False)
window["--REMOVE-PATHS--"].update(disabled=False)
window["backup_opts.stdin_from_command"].update(disabled=True)
elif value in ("files_from", "files_from_verbatim", "files_from_raw"):
window["backup_opts.paths"].update(visible=True)
window["--ADD-PATHS-FILE-BUTTON--"].update(disabled=False)
window["--ADD-PATHS-FOLDER-BUTTON--"].update(disabled=True)
window["--ADD-PATHS-MANUALLY--"].update(disabled=False)
window["--REMOVE-PATHS--"].update(disabled=False)
window["backup_opts.stdin_from_command"].update(disabled=True)
continue
if event in (
"--ADD-PATHS-FILE--",
"--ADD-PATHS-FOLDER--",

View file

@ -295,7 +295,7 @@ class ResticRunner:
if self.additional_parameters
else ""
)
_cmd = f'"{self._binary}" {additional_parameters}{cmd}{self.generic_arguments}'
_cmd = f'"{self._binary}"{additional_parameters}{self.generic_arguments} {cmd}'
self._executor_running = True
self.write_logs(f"Running command: [{_cmd}]", level="debug")
@ -781,6 +781,7 @@ class ResticRunner:
tags: List[str] = [],
one_file_system: bool = False,
read_from_stdin: bool = False,
stdin_from_command: str = None,
stdin_filename: str = "stdin.data",
additional_backup_only_parameters: str = None,
) -> Union[bool, str, dict]:
@ -790,11 +791,9 @@ class ResticRunner:
kwargs = locals()
kwargs.pop("self")
if read_from_stdin:
cmd = "backup --stdin"
if stdin_filename:
cmd += f' --stdin-filename "{stdin_filename}"'
else:
cmd = "backup"
if not read_from_stdin and not stdin_from_command:
# Handle various source types
if source_type in [
"files_from",
@ -883,6 +882,8 @@ class ResticRunner:
"Parameter --use-fs-snapshot was given, which is only compatible with Windows",
level="warning",
)
for tag in tags:
if tag:
tag = tag.strip()
@ -890,6 +891,15 @@ class ResticRunner:
if additional_backup_only_parameters:
cmd += " {}".format(additional_backup_only_parameters)
if read_from_stdin:
cmd += " --stdin"
if stdin_filename:
cmd += f' --stdin-filename "{stdin_filename}"'
if stdin_from_command:
if stdin_filename:
cmd += f' --stdin-filename "{stdin_filename}"'
cmd += f" --stdin-from-command -- {stdin_from_command}"
# Run backup without json output, as we could not compute the cloud errors in json output via regexes
json_output = self.json_output
self.json_output = False

View file

@ -108,6 +108,7 @@ en:
files_from: From file
files_from_verbatim: From verbatim
files_from_raw: From raw
stdin_from_command: Standard input from command
# retention policiy
retention_policy: Retention policy

View file

@ -109,6 +109,7 @@ fr:
files_from: Liste depuis un fichier
files_from_verbatim: Liste depuis un fichier "exact"
files_from_raw: Liste depuis un fichier "raw"
stdin_from_command: Entrée standard depuis une commande
# retention policy
retention_policy: Politique de rétention