Skip to content

Commit 945aade

Browse files
committed
quadlet kube: correctly mark unit as failed
When no containers could be started we need to make sure the unit status reflects this. This means we should not send the READ=1 message and not keep the service container running when we were unable to start any container. There is the question what should happen when only a subset was started. For systemd we can only be either running or failed. And as podman kube play also just keeps the partial started pods running I opted to let systemd keep considering this as success. Fixes containers#20667 Fixes https://issues.redhat.com/browse/RHEL-80471 Signed-off-by: Paul Holzinger <[email protected]>
1 parent 518773a commit 945aade

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

pkg/domain/infra/abi/play.go

+28-5
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,19 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
283283
var configMaps []v1.ConfigMap
284284

285285
ranContainers := false
286+
// set the ranContainers bool to true if at least one container was successfully started.
287+
setRanContainers := func(r *entities.PlayKubeReport) {
288+
if !ranContainers {
289+
for _, p := range r.Pods {
290+
// If the list of container errors is less then the total number of pod containers then we know it didn't start.
291+
if len(p.ContainerErrors) < len(p.Containers)+len(p.InitContainers) {
292+
ranContainers = true
293+
break
294+
}
295+
}
296+
}
297+
}
298+
286299
// FIXME: both, the service container and the proxies, should ideally
287300
// be _state_ of an object. The Kube code below is quite Spaghetti-code
288301
// which we should refactor at some point to make it easier to extend
@@ -364,7 +377,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
364377

365378
report.Pods = append(report.Pods, r.Pods...)
366379
validKinds++
367-
ranContainers = true
380+
setRanContainers(r)
368381
case "DaemonSet":
369382
var daemonSetYAML v1apps.DaemonSet
370383

@@ -380,7 +393,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
380393

381394
report.Pods = append(report.Pods, r.Pods...)
382395
validKinds++
383-
ranContainers = true
396+
setRanContainers(r)
384397
case "Deployment":
385398
var deploymentYAML v1apps.Deployment
386399

@@ -396,7 +409,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
396409

397410
report.Pods = append(report.Pods, r.Pods...)
398411
validKinds++
399-
ranContainers = true
412+
setRanContainers(r)
400413
case "Job":
401414
var jobYAML v1.Job
402415

@@ -412,7 +425,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
412425

413426
report.Pods = append(report.Pods, r.Pods...)
414427
validKinds++
415-
ranContainers = true
428+
setRanContainers(r)
416429
case "PersistentVolumeClaim":
417430
var pvcYAML v1.PersistentVolumeClaim
418431

@@ -473,10 +486,14 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
473486
return nil, fmt.Errorf("YAML document does not contain any supported kube kind")
474487
}
475488

489+
if !options.ServiceContainer {
490+
return report, nil
491+
}
492+
476493
// If we started containers along with a service container, we are
477494
// running inside a systemd unit and need to set the main PID.
478495

479-
if options.ServiceContainer && ranContainers {
496+
if ranContainers {
480497
switch len(notifyProxies) {
481498
case 0: // Optimization for containers/podman/issues/17345
482499
// No container needs sdnotify, so we can mark the
@@ -509,6 +526,12 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
509526
}
510527

511528
report.ServiceContainerID = serviceContainer.ID()
529+
} else if serviceContainer != nil {
530+
// No containers started, make sure to stop the service container.
531+
// Note because the pods still do exists and are not removed by default we cannot remove it.
532+
if err := serviceContainer.StopWithTimeout(0); err != nil {
533+
logrus.Errorf("Failed to stop service container: %v", err)
534+
}
512535
}
513536

514537
return report, nil

test/system/252-quadlet.bats

+53
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,59 @@ EOF
11071107
service_cleanup $QUADLET_SERVICE_NAME inactive
11081108
}
11091109

1110+
# https://github.com/containers/podman/issues/20667
1111+
@test "quadlet kube - start error" {
1112+
local port=$(random_free_port)
1113+
# Create the YAMl file
1114+
pod_name="p-$(safename)"
1115+
container_name="c-$(safename)"
1116+
yaml_source="$PODMAN_TMPDIR/start_err$(safename).yaml"
1117+
cat >$yaml_source <<EOF
1118+
apiVersion: v1
1119+
kind: Pod
1120+
metadata:
1121+
name: $pod_name
1122+
spec:
1123+
containers:
1124+
- command:
1125+
- "top"
1126+
image: $IMAGE
1127+
name: $container_name
1128+
ports:
1129+
- containerPort: 80
1130+
hostPort: $port
1131+
EOF
1132+
1133+
# Bind the port to force a an error when starting the pod
1134+
timeout --foreground -v --kill=10 10 nc -l 127.0.0.1 $port &
1135+
nc_pid=$!
1136+
1137+
# Create the Quadlet file
1138+
local quadlet_file=$PODMAN_TMPDIR/start_err_$(safename).kube
1139+
cat > $quadlet_file <<EOF
1140+
[Kube]
1141+
Yaml=${yaml_source}
1142+
EOF
1143+
1144+
run_quadlet "$quadlet_file"
1145+
1146+
run -0 systemctl daemon-reload
1147+
1148+
echo "$_LOG_PROMPT systemctl start $QUADLET_SERVICE_NAME"
1149+
run systemctl start $QUADLET_SERVICE_NAME
1150+
echo $output
1151+
assert $status -eq 1 "systemctl start should report failure"
1152+
1153+
run -0 systemctl show --property=ActiveState $QUADLET_SERVICE_NAME
1154+
assert "$output" == "ActiveState=failed" "unit must be in failed state"
1155+
1156+
echo "$_LOG_PROMPT journalctl -u $QUADLET_SERVICE_NAME"
1157+
run -0 journalctl -eu $QUADLET_SERVICE_NAME
1158+
assert "$output" =~ "$port: bind: address already in use" "journal contains the real podman start error"
1159+
1160+
kill "$nc_pid"
1161+
}
1162+
11101163
@test "quadlet - image files" {
11111164
local quadlet_tmpdir=$PODMAN_TMPDIR/quadlets
11121165

0 commit comments

Comments
 (0)