From 988b77897a72f2ba7adb54c020d2ac6e5355448c Mon Sep 17 00:00:00 2001 From: AdityaShome Date: Wed, 12 Aug 2026 01:04:18 +0530 Subject: [PATCH] fix reversed bytes.Contains args in CheckMachine's systemd state check and add a test for it Signed-off-by: AdityaShome --- platform/platform.go | 18 +++++++++++++-- platform/platform_test.go | 48 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 platform/platform_test.go diff --git a/platform/platform.go b/platform/platform.go index 2e14abd36..858132f5d 100644 --- a/platform/platform.go +++ b/platform/platform.go @@ -341,6 +341,19 @@ func NewMachines(c Cluster, userdata *conf.UserData, n int) ([]Machine, error) { return machs, nil } +// systemRunningState classifies `systemctl is-system-running` output. keep +// is true while still on the way to "running"; anything else, including +// empty output, means stop retrying. +func systemRunningState(raw []byte) (state string, keep bool) { + state = strings.TrimSpace(string(raw)) + switch state { + case "initializing", "starting", "running", "stopping": + return state, true + default: + return state, false + } +} + // CheckMachine tests a machine for various error conditions such as ssh // being available and no systemd units failing at the time ssh is reachable. // It also ensures the remote system is running Flatcar Container Linux. @@ -353,11 +366,12 @@ func CheckMachine(ctx context.Context, m Machine) error { return err } out, stderr, err := m.SSH("systemctl is-system-running") - if !bytes.Contains([]byte("initializing starting running stopping"), out) { + state, keep := systemRunningState(out) + if !keep { return nil // stop retrying if the system went haywire, e.g., "degraded" } jobs := "" - if bytes.Contains([]byte("starting"), out) { + if state == "starting" { startingOut, startingStderr, startingErr := m.SSH("systemctl list-jobs") jobs = fmt.Sprintf(", systemctl list-jobs returned stdout: %q, stderr: %q, err: %v", startingOut, startingStderr, startingErr) } diff --git a/platform/platform_test.go b/platform/platform_test.go new file mode 100644 index 000000000..d3bb26bc3 --- /dev/null +++ b/platform/platform_test.go @@ -0,0 +1,48 @@ +// Copyright 2026 The Flatcar Maintainers. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package platform + +import "testing" + +func TestSystemRunningState(t *testing.T) { + tests := []struct { + name string + raw string + wantState string + wantKeep bool + }{ + {"running", "running", "running", true}, + {"running with trailing newline", "running\n", "running", true}, + {"initializing", "initializing", "initializing", true}, + {"starting", "starting", "starting", true}, + {"stopping", "stopping", "stopping", true}, + {"degraded", "degraded", "degraded", false}, + {"maintenance", "maintenance", "maintenance", false}, + {"offline", "offline", "offline", false}, + // A blank/empty SSH response (e.g. a transient connection hiccup) + // must not be mistaken for an in-progress state. + {"empty output", "", "", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotState, gotKeep := systemRunningState([]byte(tt.raw)) + if gotState != tt.wantState || gotKeep != tt.wantKeep { + t.Errorf("systemRunningState(%q) = (%q, %v), want (%q, %v)", + tt.raw, gotState, gotKeep, tt.wantState, tt.wantKeep) + } + }) + } +}