fix(service): detect registry-prefixed Grafana server images (#10617)

This commit is contained in:
Andras Bacsai
2026-10-04 13:39:19 +02:00
committed by GitHub
parent 1b9f0ccaee
commit b235a480b2
2 changed files with 39 additions and 2 deletions
+17 -2
View File
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Services\ContainerStatusAggregator;
use App\Services\DockerImageParser;
use App\Support\DomainPortOverrides;
use App\Support\ResourceStartActivity;
use App\Traits\Auditable;
@@ -642,7 +643,7 @@ class Service extends BaseModel
}
$fields->put('Unleash', $data->toArray());
break;
case $this->isGrafanaImage($image->toString()):
case $this->isGrafanaServerImage($application->image):
$data = collect([]);
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GRAFANA')->first();
$data = $data->merge([
@@ -1417,8 +1418,22 @@ class Service extends BaseModel
return $fields;
}
private function isGrafanaImage(string $image): bool
/**
* Determine whether the given image is an actual Grafana server image
* (grafana/grafana, grafana/grafana-oss, grafana/grafana-enterprise),
* optionally prefixed by a registry host. Other Grafana-published images
* such as grafana/loki, grafana/promtail and grafana/tempo are excluded.
*/
private function isGrafanaServerImage(string $image): bool
{
$parsedImage = (new DockerImageParser)->parse($image);
$image = $parsedImage->getImageName();
// The parser recognizes registry hosts with dots or ports, but not bare localhost.
if ($parsedImage->getRegistryUrl() === '' && str_starts_with($image, 'localhost/')) {
$image = substr($image, strlen('localhost/'));
}
return in_array($image, [
'grafana/grafana',
'grafana/grafana-oss',
+22
View File
@@ -44,6 +44,28 @@ it('only adds Grafana extra fields for Grafana server images', function (string
'loki' => ['grafana/loki:latest', false],
'promtail' => ['grafana/promtail:latest', false],
'tempo' => ['grafana/tempo:latest', false],
'registry.example.com grafana' => ['registry.example.com/grafana/grafana:latest', true],
'registry.example.com grafana-oss' => ['registry.example.com/grafana/grafana-oss:latest', true],
'registry.example.com grafana-enterprise' => ['registry.example.com/grafana/grafana-enterprise:latest', true],
'registry.example.com loki' => ['registry.example.com/grafana/loki:latest', false],
'registry.example.com promtail' => ['registry.example.com/grafana/promtail:latest', false],
'registry.example.com tempo' => ['registry.example.com/grafana/tempo:latest', false],
'registry.example.com:5000 grafana' => ['registry.example.com:5000/grafana/grafana:latest', true],
'registry.example.com:5000 grafana-oss' => ['registry.example.com:5000/grafana/grafana-oss:latest', true],
'registry.example.com:5000 grafana-enterprise' => ['registry.example.com:5000/grafana/grafana-enterprise:latest', true],
'registry.example.com:5000 loki' => ['registry.example.com:5000/grafana/loki:latest', false],
'registry.example.com:5000 promtail' => ['registry.example.com:5000/grafana/promtail:latest', false],
'registry.example.com:5000 tempo' => ['registry.example.com:5000/grafana/tempo:latest', false],
'localhost registry' => ['localhost/grafana/grafana:latest', true],
'unrelated namespace' => ['other/grafana/grafana:latest', false],
'localhost as registry namespace' => ['registry.example.com/localhost/grafana/grafana:latest', false],
'nested registry namespace' => ['registry.example.com/team/grafana/grafana:latest', false],
'nested registry namespace oss' => ['registry.example.com:5000/team/grafana/grafana-oss:latest', false],
'nested registry namespace enterprise' => ['registry.example.com/team/grafana/grafana-enterprise:latest', false],
'similar repository name' => ['grafana/grafana-custom:latest', false],
'registry port without tag' => ['registry.example.com:5000/grafana/grafana', true],
'digest' => ['grafana/grafana@sha256:'.str_repeat('a', 64), true],
'registry port with digest' => ['registry.example.com:5000/grafana/grafana@sha256:'.str_repeat('a', 64), true],
]);
it('exposes Jean Server authentication and access settings', function () {