omni/internal/integration/kernelargs_test.go
Edward Sammut Alessi d3ae77c0cc
chore: bump copyright to 2026
Bump copyright for conformance to 2026

Signed-off-by: Edward Sammut Alessi <edward.sammutalessi@siderolabs.com>
2026-01-21 15:30:49 +01:00

144 lines
5.0 KiB
Go

// Copyright (c) 2026 Sidero Labs, Inc.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//go:build integration
package integration_test
import (
"context"
"slices"
"strings"
"testing"
"time"
"github.com/blang/semver/v4"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
xmaps "github.com/siderolabs/gen/maps"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/siderolabs/omni/client/pkg/omni/resources/omni"
)
func testKernelArgsUpdate(t *testing.T, options *TestOptions) {
ctx, cancel := context.WithTimeout(t.Context(), 15*time.Minute)
defer cancel()
options.claimMachines(t, 2)
clusterName := "integration-kernel-args-update"
version, err := semver.ParseTolerant(options.MachineOptions.TalosVersion)
require.NoError(t, err)
// Create a cluster to make sure that we have Talos installed on a machine
t.Run(
"ClusterShouldBeCreated",
CreateCluster(t.Context(), options.omniClient, ClusterOptions{
Name: clusterName,
ControlPlanes: 1,
Workers: 1,
MachineOptions: options.MachineOptions,
ScalingTimeout: options.ScalingTimeout,
SkipExtensionCheckOnCreate: options.SkipExtensionsCheckOnCreate,
// Pick two machines depending on the Talos version:
// - 1.12 or later; one booted with UKI and another booted with non-UKI, as kernel args upgrades are supported with Talos 1.12 and later.
// - earlier versions; pick machines booted with UKI, because they are the only ones that support kernel args upgrades.
PickFilterFunc: func(ms *omni.MachineStatus, alreadyPicked []*omni.MachineStatus) bool {
canUseUKICmdline := version.Major > 1 || (version.Major == 1 && version.Minor >= 12)
// If we can't let grub to use UKI cmdline, we can only pick machines with UKI.
if !canUseUKICmdline {
return ms.TypedSpec().Value.GetSecurityState().GetBootedWithUki()
}
alreadyPickedUKI := slices.ContainsFunc(alreadyPicked, func(m *omni.MachineStatus) bool { return m.TypedSpec().Value.GetSecurityState().GetBootedWithUki() })
alreadyPickedNonUKI := slices.ContainsFunc(alreadyPicked, func(m *omni.MachineStatus) bool { return !m.TypedSpec().Value.GetSecurityState().GetBootedWithUki() })
if alreadyPickedUKI && alreadyPickedNonUKI {
return true
}
isUKI := ms.TypedSpec().Value.GetSecurityState().GetBootedWithUki()
if isUKI && !alreadyPickedUKI {
return true
}
return !isUKI && !alreadyPickedNonUKI
},
}),
)
assertClusterAndAPIReady(t, clusterName, options)
omniState := options.omniClient.Omni().State()
kernelArgsMap := make(map[string]*omni.KernelArgs, 2)
t.Run("ClusterMachineKernelArgsShouldBeUpdated", func(t *testing.T) {
clusterMachines, err := safe.StateListAll[*omni.ClusterMachine](ctx, omniState, state.WithLabelQuery(resource.LabelEqual(omni.LabelCluster, clusterName)))
require.NoError(t, err)
for machine := range clusterMachines.All() {
machineID := machine.Metadata().ID()
t.Logf("picked machine ID: %s", machineID)
kernelArgs, err := safe.StateModifyWithResult(ctx, omniState, omni.NewKernelArgs(machineID), func(res *omni.KernelArgs) error {
// make sure that we actually change the args by checking the existing value
args1 := []string{"foo=bar", "baz=qux"}
args2 := []string{"baz=qux", "foo=bar"}
if slices.Equal(res.TypedSpec().Value.Args, args1) {
res.TypedSpec().Value.Args = args2
return nil
}
res.TypedSpec().Value.Args = args1
return nil
})
require.NoError(t, err)
kernelArgsMap[machineID] = kernelArgs
}
// verify that the new kernel args appear in the kernel cmdline
rtestutils.AssertResources(ctx, t, omniState, xmaps.Keys(kernelArgsMap), func(r *omni.MachineStatus, assert *assert.Assertions) {
assert.Contains(r.TypedSpec().Value.KernelCmdline, strings.Join(kernelArgsMap[r.Metadata().ID()].TypedSpec().Value.Args, " "), resourceDetails(r))
})
})
t.Run("ClusterShouldBeDestroyed", AssertDestroyCluster(t.Context(), options.omniClient.Omni().State(), clusterName, false, false))
updatedKernelArgsMap := make(map[string]*omni.KernelArgs, 2)
t.Run("MachineKernelArgsShouldBeUpdatedInMaintenance", func(t *testing.T) {
for machineID := range kernelArgsMap {
updatedKernelArgs, err := safe.StateModifyWithResult(ctx, omniState, omni.NewKernelArgs(machineID), func(res *omni.KernelArgs) error {
res.TypedSpec().Value.Args = []string{"maintenance=true"}
return nil
})
require.NoError(t, err)
updatedKernelArgsMap[machineID] = updatedKernelArgs
}
// verify that the new kernel args appear in the kernel cmdline
rtestutils.AssertResources(ctx, t, omniState, xmaps.Keys(updatedKernelArgsMap), func(r *omni.MachineStatus, assert *assert.Assertions) {
assert.Contains(r.TypedSpec().Value.KernelCmdline, strings.Join(updatedKernelArgsMap[r.Metadata().ID()].TypedSpec().Value.Args, " "), resourceDetails(r))
})
})
}