allow to include volumes in backup and restore

Signed-off-by: Simon L <szaimen@e.mail.de>
This commit is contained in:
Simon L 2023-05-17 20:48:08 +02:00
parent 1513d69a8d
commit 9f19026885
7 changed files with 68 additions and 23 deletions

View file

@ -24,6 +24,14 @@ for directory in "${VOLUME_DIRS[@]}"; do
exit 1 exit 1
fi fi
done done
# Test if default volumes are there
DEFAULT_VOLUMES=(nextcloud_aio_apache nextcloud_aio_nextcloud nextcloud_aio_database nextcloud_aio_database_dump nextcloud_aio_elasticsearch nextcloud_aio_nextcloud_data nextcloud_aio_mastercontainer)
for volume in "${DEFAULT_VOLUMES[@]}"; do
if ! mountpoint -q "/nextcloud_aio_volumes/$volume"; then
echo "$volume is missing which is not intended."
exit 1
fi
done
# Check if target is mountpoint # Check if target is mountpoint
if ! mountpoint -q /mnt/borgbackup; then if ! mountpoint -q /mnt/borgbackup; then

View file

@ -15,6 +15,7 @@ OUTPUT="$(cat /tmp/containers.json)"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].internal_port)')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].internal_port)')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].secrets)')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].secrets)')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].devices)')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].devices)')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[].backup_volumes)')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-watchtower"))')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-watchtower"))')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-domaincheck"))')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-domaincheck"))')"
OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-borgbackup"))')" OUTPUT="$(echo "$OUTPUT" | jq 'del(.services[] | select(.container_name == "nextcloud-aio-borgbackup"))')"

View file

@ -106,6 +106,13 @@
"apparmor_unconfined": { "apparmor_unconfined": {
"type": "boolean" "type": "boolean"
}, },
"backup_volumes": {
"type": "array",
"items": {
"type": "string",
"pattern": "^nextcloud_aio_[a-z_]+$"
}
},
"volumes": { "volumes": {
"type": "array", "type": "array",
"items": { "items": {
@ -119,7 +126,8 @@
}, },
"source": { "source": {
"type": "string", "type": "string",
"pattern": "^(([a-z_]+)|(%[A-Z_]+%))$" }, "pattern": "^((nextcloud_aio_[a-z_]+)|(%[A-Z_]+%))$"
},
"writeable": { "writeable": {
"type": "boolean" "type": "boolean"
} }

View file

@ -41,7 +41,11 @@
"writeable": true "writeable": true
} }
], ],
"restart": "unless-stopped" "restart": "unless-stopped",
"backup_volumes": [
"nextcloud_aio_nextcloud",
"nextcloud_aio_apache"
]
}, },
{ {
"container_name": "nextcloud-aio-database", "container_name": "nextcloud-aio-database",
@ -75,7 +79,11 @@
], ],
"stop_grace_period": 1800, "stop_grace_period": 1800,
"restart": "unless-stopped", "restart": "unless-stopped",
"shm_size": 268435456 "shm_size": 268435456,
"backup_volumes": [
"nextcloud_aio_database",
"nextcloud_aio_database_dump"
]
}, },
{ {
"container_name": "nextcloud-aio-nextcloud", "container_name": "nextcloud-aio-nextcloud",
@ -167,6 +175,9 @@
"restart": "unless-stopped", "restart": "unless-stopped",
"devices": [ "devices": [
"/dev/dri" "/dev/dri"
],
"backup_volumes": [
"nextcloud_aio_nextcloud"
] ]
}, },
{ {
@ -270,31 +281,11 @@
"destination": "/root", "destination": "/root",
"writeable": true "writeable": true
}, },
{
"source": "nextcloud_aio_nextcloud",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_nextcloud",
"writeable": true
},
{ {
"source": "%NEXTCLOUD_DATADIR%", "source": "%NEXTCLOUD_DATADIR%",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data", "destination": "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data",
"writeable": true "writeable": true
}, },
{
"source": "nextcloud_aio_database",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_database",
"writeable": true
},
{
"source": "nextcloud_aio_database_dump",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_database_dump",
"writeable": true
},
{
"source": "nextcloud_aio_apache",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_apache",
"writeable": true
},
{ {
"source": "nextcloud_aio_mastercontainer", "source": "nextcloud_aio_mastercontainer",
"destination": "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer", "destination": "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer",

View file

@ -27,6 +27,8 @@ class Container {
private array $capAdd; private array $capAdd;
private int $shmSize; private int $shmSize;
private bool $apparmorUnconfined; private bool $apparmorUnconfined;
/** @var string[] */
private array $backupVolumes;
private DockerActionManager $dockerActionManager; private DockerActionManager $dockerActionManager;
public function __construct( public function __construct(
@ -45,6 +47,7 @@ class Container {
array $capAdd, array $capAdd,
int $shmSize, int $shmSize,
bool $apparmorUnconfined, bool $apparmorUnconfined,
array $backupVolumes,
DockerActionManager $dockerActionManager DockerActionManager $dockerActionManager
) { ) {
$this->identifier = $identifier; $this->identifier = $identifier;
@ -62,6 +65,7 @@ class Container {
$this->capAdd = $capAdd; $this->capAdd = $capAdd;
$this->shmSize = $shmSize; $this->shmSize = $shmSize;
$this->apparmorUnconfined = $apparmorUnconfined; $this->apparmorUnconfined = $apparmorUnconfined;
$this->backupVolumes = $backupVolumes;
$this->dockerActionManager = $dockerActionManager; $this->dockerActionManager = $dockerActionManager;
} }
@ -105,6 +109,10 @@ class Container {
return $this->capAdd; return $this->capAdd;
} }
public function GetBackupVolumes() : array {
return $this->backupVolumes;
}
public function GetPorts() : ContainerPorts { public function GetPorts() : ContainerPorts {
return $this->ports; return $this->ports;
} }

View file

@ -228,6 +228,11 @@ class ContainerDefinitionFetcher
$apparmorUnconfined = $entry['apparmor_unconfined']; $apparmorUnconfined = $entry['apparmor_unconfined'];
} }
$backupVolumes = [];
if (isset($entry['backup_volumes'])) {
$backupVolumes = $entry['backup_volumes'];
}
$containers[] = new Container( $containers[] = new Container(
$entry['container_name'], $entry['container_name'],
$displayName, $displayName,
@ -244,6 +249,7 @@ class ContainerDefinitionFetcher
$capAdd, $capAdd,
$shmSize, $shmSize,
$apparmorUnconfined, $apparmorUnconfined,
$backupVolumes,
$this->container->get(DockerActionManager::class) $this->container->get(DockerActionManager::class)
); );
} }

View file

@ -429,6 +429,11 @@ class DockerActionManager
if ($container->GetIdentifier() === 'nextcloud-aio-borgbackup') { if ($container->GetIdentifier() === 'nextcloud-aio-borgbackup') {
// Additional backup directories // Additional backup directories
$mounts = []; $mounts = [];
foreach ($this->getAllBackupVolumes() as $additionalBackupVolumes) {
if ($additionalBackupVolumes !== '') {
$mounts[] = ["Type" => "volume", "Source" => $additionalBackupVolumes, "Target" => "/nextcloud_aio_volumes/" . $additionalBackupVolumes, "ReadOnly" => false];
}
}
foreach ($this->configurationManager->GetAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) { foreach ($this->configurationManager->GetAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
if ($additionalBackupDirectories !== '') { if ($additionalBackupDirectories !== '') {
if (!str_starts_with($additionalBackupDirectories, '/')) { if (!str_starts_with($additionalBackupDirectories, '/')) {
@ -503,6 +508,24 @@ class DockerActionManager
} }
} }
private function getBackupVolumes(string $id) : array
{
$container = $this->containerDefinitionFetcher->GetContainerById($id);
$backupVolumes = $container->GetBackupVolumes();
foreach ($container->GetDependsOn() as $dependency) {
$backupVolumes[] = $this->getBackupVolumes($dependency);
}
return $backupVolumes;
}
private function getAllBackupVolumes() : array {
$id = 'nextcloud-aio-apache';
return array_unique($this->getBackupVolumes($id));
}
private function GetRepoDigestsOfContainer(string $containerName) : ?array { private function GetRepoDigestsOfContainer(string $containerName) : ?array {
try { try {
$containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName)); $containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));