diff --git a/src/include/ABHelper.php b/src/include/ABHelper.php index 08dcb3b..0cda25a 100644 --- a/src/include/ABHelper.php +++ b/src/include/ABHelper.php @@ -361,10 +361,8 @@ public static function backupContainer($container, $destination) { $tarExcludes = []; if (!empty($containerSettings['exclude'])) { - self::backupLog("Container got excludes! " . PHP_EOL . print_r($containerSettings['exclude'], true), self::LOGLEVEL_DEBUG); - $excludes = explode("\r\n", $containerSettings['exclude']); - if (!empty($excludes)) { - foreach ($excludes as $exclude) { + self::backupLog("Container got excludes! " . implode(", ", $containerSettings['exclude']), self::LOGLEVEL_DEBUG); + foreach ($containerSettings['exclude'] as $exclude) { $exclude = rtrim($exclude, "/"); if (!empty($exclude)) { if (($volumeKey = array_search($exclude, $volumes)) !== false) { @@ -375,7 +373,6 @@ public static function backupContainer($container, $destination) { $tarExcludes[] = '--exclude ' . escapeshellarg($exclude); } } - } } if (!empty($abSettings->globalExclusions)) { @@ -502,7 +499,7 @@ public static function abortRequested() { * @param $container * @return array */ - public static function getContainerVolumes($container) { + public static function getContainerVolumes($container, $skipExclusionCheck = false) { global $abSettings; $volumes = []; @@ -512,6 +509,16 @@ public static function getContainerVolumes($container) { self::backupLog("This volume is empty (rootfs mapped??)! Ignoring.", self::LOGLEVEL_DEBUG); continue; } + + if (!$skipExclusionCheck) { + $containerSettings = $abSettings->getContainerSpecificSettings($container['Name']); + + if (in_array($hostPath, $containerSettings['exclude'])) { + self::backupLog("Ignoring '$hostPath' because its listed in containers exclusions list!", self::LOGLEVEL_DEBUG); + continue; + } + } + if (!file_exists($hostPath)) { self::backupLog("'$hostPath' does NOT exist! Please check your mappings! Skipping it for now.", self::LOGLEVEL_ERR); continue; diff --git a/src/include/ABSettings.php b/src/include/ABSettings.php index d675c2f..60f7047 100644 --- a/src/include/ABSettings.php +++ b/src/include/ABSettings.php @@ -51,7 +51,7 @@ class ABSettings { // The following are hidden, container special default settings 'skip' => 'no', - 'exclude' => '', + 'exclude' => [], 'dontStop' => 'no', 'backupExtVolumes' => 'no' ]; @@ -111,6 +111,23 @@ public function __construct() { case 'settingsVersion': $this::$settingsVersion = $value; break; + case 'containerSettings': + /** + * Container specific patches + */ + foreach ($value as $containerName => $containerSettings) { + $paths = explode("\r\n", $containerSettings['exclude']); + $newPaths = []; + foreach ($paths as $pathKey => $path) { + if (empty(trim($path))) { + continue; // Skip empty lines + } + $newPaths[] = rtrim($path, '/'); + } + $value[$containerName]['exclude'] = $newPaths; + } + $this->$key = $value; + break; default: $this->$key = $value; break; @@ -217,7 +234,7 @@ public function getContainerSpecificSettings($name, $setEmptyToDefault = true) { * Container is unknown, init its values with empty strings = 'use default' */ foreach ($this->defaults as $setting => $value) { - $this->containerSettings[$name][$setting] = ''; + $this->containerSettings[$name][$setting] = is_array($value) ? [] : ''; } } diff --git a/src/pages/content/settings.php b/src/pages/content/settings.php index 8af6e95..208cbca 100644 --- a/src/pages/content/settings.php +++ b/src/pages/content/settings.php @@ -172,8 +172,9 @@ } - blockquote select, blockquote textarea { + blockquote select, blockquote textarea, blockquote input[type="text"] { border-bottom: ; + color: ; } @@ -574,19 +575,21 @@ class="fa fa-clock-o title">Notifications and scheduling } $image = empty($container['Icon']) ? '/plugins/dynamix.docker.manager/images/question.png' : $container['Icon']; - $volumes = ABHelper::getContainerVolumes($container); + $volumes = ABHelper::getContainerVolumes($container, true); + $containerSetting = $abSettings->getContainerSpecificSettings($container['Name'], false); + $realContainerSetting = print_r($abSettings->getContainerSpecificSettings($container['Name']), true); if (empty($volumes)) { $volumes = "No volumes - container will NOT being backed up!"; } else { foreach ($volumes as $index => $volume) { - $volumes[$index] = ' ' . $volume . ''; + $excluded = in_array($volume, $containerSetting['exclude']) ? ' - EXCLUDED! ' : ''; + $volumes[$index] = ' ' . $volume . '' . $excluded . ''; } $volumes = implode('
', $volumes); } - $containerSetting = $abSettings->getContainerSpecificSettings($container['Name'], false); - $realContainerSetting = print_r($abSettings->getContainerSpecificSettings($container['Name']), true); + $containerExcludes = implode("\r\n", $containerSetting['exclude']); echo <<$realContainerSetting @@ -625,12 +628,12 @@ class="fa fa-clock-o title">Notifications and scheduling
Excluded folders/files
One path/pattern per line. See belows "Global exclusions" for more examples.
-
+
-
Show advanced options
+
Show advanced options
Skip backup? Only stop/start
@@ -948,7 +951,8 @@ function addVolumeToExclude(element) { $path = $(element).text(); $excludeTextarea = $('#' + $(element).data('container') + '_exclude'); - if ($excludeTextarea.val().indexOf($path) !== -1) { // If existing inside textarea + if ($excludeTextarea.val().split(/\r?\n|\r|\n/g).includes($path)) { // If existing inside textarea + console.debug("Not adding this volume to exclusion: already listed!") return; } @@ -1009,17 +1013,18 @@ function checkVolumesForDuplicates() { $("code[data-container]").each(function () { let container = $(this).data('container'); let mapping = $(this).text(); - if ($('#' + container + '_exclude').val().indexOf(mapping) !== -1) { - console.debug(container, mapping, 'is excluded so ignored'); - } else if (volumeMatrix.includes(mapping)) { + + if (volumeMatrix.includes(mapping)) { affectedMappings.push(mapping); } else { volumeMatrix.push($(this).text()); } }); + console.debug("Volume dup check (affected/matrix): ", affectedMappings, volumeMatrix); + affectedMappings.forEach(function (element) { - let codeElems = $('code:contains(' + element + ')'); + let codeElems = $('code[data-container]:contains(' + element + ')'); codeElems.each(function () { $('#containerMultiMappingIssue_' + $(this).data('container')).show(); $(this).next('.multiVolumeWarn').show();