fix(api): harden service_name filter for application logs

- Match the Compose service label with format_docker_labels_to_json()
  and skip containers without labels.
- Document service_name on the preview logs endpoint and remove the
  incorrect "ignored for non-Compose applications" claim. Every
  application runs as a Compose service, so a mismatch returns 404.
- Add regression tests for service selection, the default container,
  and the exact-match 404.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-01 15:27:11 +02:00
co-authored by Claude Opus 5.5
parent 6023f4974e
commit 8bbab724e2
2 changed files with 61 additions and 5 deletions
@@ -2481,7 +2481,7 @@ class ApplicationsController extends Controller
new OA\Parameter(
name: 'service_name',
in: 'query',
description: 'For Docker Compose applications, return logs only from the Compose service with this name. Returns 404 when no running container matches. Ignored for non-Compose applications.',
description: 'Return logs only from the container of the Docker Compose service with this name. Returns 404 when no running container matches.',
required: false,
schema: new OA\Schema(type: 'string'),
),
@@ -2557,6 +2557,13 @@ class ApplicationsController extends Controller
required: false,
schema: new OA\Schema(type: 'boolean', default: false),
),
new OA\Parameter(
name: 'service_name',
in: 'query',
description: 'Return logs only from the container of the Docker Compose service with this name. Returns 404 when no running container matches.',
required: false,
schema: new OA\Schema(type: 'string'),
),
],
responses: [
new OA\Response(response: 200, description: 'Preview runtime logs.', content: new OA\JsonContent(
@@ -2615,10 +2622,7 @@ class ApplicationsController extends Controller
$matchingContainer = $containers->first(function ($container) use ($serviceName) {
$labels = data_get($container, 'Labels');
return $labels !== null && preg_match(
'/(?:^|,)com\.docker\.compose\.service='.preg_quote($serviceName, '/').'(?:,|$)/',
$labels
) === 1;
return filled($labels) && format_docker_labels_to_json($labels)->get('com.docker.compose.service') === $serviceName;
});
if (! $matchingContainer) {