Skip to content

Commit d6fa31c

Browse files
dcflachselibosley
authored andcommitted
fix(docker): refresh label icon cache by URL
- Purpose: update the Dockerman icon cache patch so label-driven icons refresh when the label URL changes. - Before: the 7.3 Docker tab cache guard could keep serving an existing cached icon even after a third-party container changed its net.unraid.docker.icon label. - Problem: that preserved the fast path but meant the rebased PR no longer fully fixed the original stale icon case. - New behavior: non-Dockerman containers track the last label icon URL, refresh icons when that URL changes, and clear cached label icons when the label is removed. - Implementation: keep Dockerman-managed containers on template-first icon resolution, prefer label URLs only for non-Dockerman containers, share persistent icons by SHA1 URL filename, and purge unused cached icon files.
1 parent cc6a800 commit d6fa31c

2 files changed

Lines changed: 67 additions & 12 deletions

File tree

emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,7 @@ function dockerUIBlockerScript($enable) {
151151
if (is_file($filename)) {
152152
$oldXML = simplexml_load_file($filename);
153153
if ($oldXML->Icon != $_POST['contIcon']) {
154-
if (!strpos($Repository,":")) $Repository .= ":latest";
155-
$iconPath = $DockerTemplates->getIcon($Repository,$Name);
156-
@unlink("$docroot/$iconPath");
157-
@unlink("{$dockerManPaths['images']}/".basename($iconPath));
154+
$DockerTemplates->purgeUnusedIconFiles($Name);
158155
}
159156
}
160157
file_put_contents($filename, $postXML);

emhttp/plugins/dynamix.docker.manager/include/DockerClient.php

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,13 +337,25 @@ public function getAllInfo($reload=false,$com=true,$communityApplications=false)
337337
// looking for a match. Bad.
338338
$labelIconUrl = $ct['Icon'] ?? null;
339339
if (!$communityApplications) {
340+
$isDockerman = ($ct['Manager'] ?? '') === 'dockerman';
341+
$preferLabelIcon = !empty($labelIconUrl) && !$isDockerman;
342+
$labelIconChanged = $preferLabelIcon
343+
&& ($tmp['icon-url'] ?? '') !== $labelIconUrl;
344+
$labelIconRemoved = !$isDockerman && !empty($tmp['icon-url']) && empty($labelIconUrl);
340345
$iconExists = !empty($tmp['icon'])
341346
&& (is_file($tmp['icon']) || is_file($docroot . $tmp['icon']));
342-
if (!$iconExists || $reload) {
343-
$tmp['icon'] = $this->getIcon($image, $name, $labelIconUrl ?: ($tmp['icon'] ?? ''));
347+
if ($labelIconRemoved) {
348+
$this->purgeUnusedIconFiles($name);
349+
$tmp['icon'] = '/plugins/dynamix.docker.manager/images/question.png';
350+
unset($tmp['icon-url']);
351+
} elseif (!$iconExists || $reload || $labelIconChanged) {
352+
$tmp['icon'] = $this->getIcon($image, $name, $labelIconUrl ?: ($tmp['icon'] ?? ''), $preferLabelIcon);
353+
if ($preferLabelIcon) $tmp['icon-url'] = $labelIconUrl;
344354
// Explicitly return the fallback asset, so that subsequent polls see
345355
// the local file instead of rerunning the expensive template scan
346356
if (empty($tmp['icon'])) $tmp['icon'] = '/plugins/dynamix.docker.manager/images/question.png';
357+
} elseif (!$preferLabelIcon) {
358+
unset($tmp['icon-url']);
347359
}
348360
}
349361
if ($ct['Running']) {
@@ -430,14 +442,28 @@ public function getAllInfo($reload=false,$com=true,$communityApplications=false)
430442
return $info;
431443
}
432444

433-
public function getIcon($Repository,$contName,$tmpIconUrl='') {
445+
private function getIconFile($imgUrl) {
446+
return sprintf('%s-%s.png', 'icon', sha1($imgUrl));
447+
}
448+
449+
private function getIconRamPath($contName, $imgUrl) {
450+
global $dockerManPaths;
451+
return sprintf('%s/%s-%s', $dockerManPaths['images-ram'], $contName, $this->getIconFile($imgUrl));
452+
}
453+
454+
public function getIcon($Repository,$contName,$iconUrl='',$preferIconUrl=false) {
434455
global $docroot, $dockerManPaths;
435-
$imgUrl = $this->getTemplateValue($Repository, 'Icon','all',$contName);
436-
if (!$imgUrl) $imgUrl = $tmpIconUrl;
456+
if ($preferIconUrl) {
457+
$imgUrl = $iconUrl ?: $this->getTemplateValue($Repository, 'Icon','all',$contName);
458+
} else {
459+
$imgUrl = $this->getTemplateValue($Repository, 'Icon','all',$contName);
460+
if (!$imgUrl) $imgUrl = $iconUrl;
461+
}
437462
if (!$imgUrl || trim($imgUrl) == "/plugins/dynamix.docker.manager/images/question.png") return '';
438463

439-
$iconRAM = sprintf('%s/%s-%s.png', $dockerManPaths['images-ram'], $contName, 'icon');
440-
$icon = sprintf('%s/%s-%s.png', $dockerManPaths['images'], $contName, 'icon');
464+
$iconFile = $this->getIconFile($imgUrl);
465+
$iconRAM = $this->getIconRamPath($contName, $imgUrl);
466+
$icon = sprintf('%s/%s', $dockerManPaths['images'], $iconFile);
441467

442468
if (!is_dir(dirname($iconRAM))) mkdir(dirname($iconRAM), 0755, true);
443469
if (!is_dir(dirname($icon))) mkdir(dirname($icon), 0755, true);
@@ -447,14 +473,46 @@ public function getIcon($Repository,$contName,$tmpIconUrl='') {
447473
@copy($icon, $iconRAM);
448474
}
449475
if (!is_file($icon) && is_file($iconRAM)) {
450-
@copy($iconRAM,$icon);
476+
@copy($iconRAM, $icon);
451477
}
452478
if (!is_file($iconRAM)) {
453479
my_logger("$contName: Could not download icon $imgUrl");
454480
}
481+
else {
482+
$this->purgeUnusedIconFiles($contName, $iconFile);
483+
}
455484

456485
return (is_file($iconRAM)) ? str_replace($docroot, '', $iconRAM) : '';
457486
}
487+
488+
public function purgeUnusedIconFiles($contName, $keepIcon='') {
489+
global $docroot, $dockerManPaths;
490+
491+
$icon_glob = sprintf('%s/%s-*.png', $dockerManPaths['images-ram'], $contName);
492+
$ramFiles = glob($icon_glob);
493+
foreach ($ramFiles as $filename) {
494+
if ( ($keepIcon === '') || !(strpos($filename, $keepIcon) !== false) ) {
495+
@unlink($filename);
496+
}
497+
}
498+
499+
$icon_glob = sprintf('%s/%s*.png', $dockerManPaths['images'], $contName);
500+
foreach (glob($icon_glob) as $filename) {
501+
if ( ($keepIcon === '') || !(strpos($filename, $keepIcon) !== false) ) {
502+
@unlink($filename);
503+
}
504+
}
505+
506+
foreach ($ramFiles as $ramFile) {
507+
if ( strpos($ramFile, '-icon-') !== false ) {
508+
$suffix = substr($ramFile, strrpos($ramFile, '-icon-') + 6);
509+
if ( $suffix && !glob($dockerManPaths['images-ram'].'/*icon-'.$suffix) ) {
510+
$filename = sprintf('%s/icon-%s', $dockerManPaths['images'], $suffix);
511+
@unlink($filename);
512+
}
513+
}
514+
}
515+
}
458516
}
459517

460518
####################################

0 commit comments

Comments
 (0)