Noel Georgi 01bb294af6
fix(ci): provision tests
Fix the provision-0 cron tests.
Support zstd disk images for `talosctl cluster create`.

Signed-off-by: Noel Georgi <git@frezbo.dev>
2025-05-02 08:28:11 +05:30

299 lines
9.4 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//go:build integration_provision
package provision
import (
"fmt"
"path/filepath"
"github.com/siderolabs/talos/cmd/talosctl/pkg/mgmt/helpers"
"github.com/siderolabs/talos/pkg/images"
"github.com/siderolabs/talos/pkg/machinery/config/machine"
"github.com/siderolabs/talos/pkg/machinery/constants"
)
//nolint:maligned
type upgradeSpec struct {
ShortName string
SourceKernelPath string
SourceInitramfsPath string
SourceDiskImagePath string
SourceInstallerImage string
SourceVersion string
SourceK8sVersion string
TargetInstallerImage string
TargetVersion string
TargetK8sVersion string
SkipKubeletUpgrade bool
ControlplaneNodes int
WorkerNodes int
UpgradeStage bool
WithEncryption bool
WithBios bool
WithApplyConfig bool
}
const (
// These versions should be kept in sync with Makefile variable RELEASES.
previousRelease = "v1.9.5"
stableRelease = "v1.10.0" // or soon-to-be-stable
// The current version (the one being built on CI) is DefaultSettings.CurrentVersion.
// Command to find Kubernetes version for past releases:
//
// git show ${TAG}:pkg/machinery/constants/constants.go | grep KubernetesVersion
previousK8sVersion = "1.32.3" // constants.DefaultKubernetesVersion in the previousRelease
stableK8sVersion = "1.33.0" // constants.DefaultKubernetesVersion in the stableRelease
currentK8sVersion = constants.DefaultKubernetesVersion
)
// upgradePreviousToStable upgrades from the previous Talos release to the stable release.
func upgradePreviousToStable() upgradeSpec {
return upgradeSpec{
ShortName: fmt.Sprintf("%s-%s", previousRelease, stableRelease),
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.KernelAsset)),
SourceInitramfsPath: helpers.ArtifactPath(
filepath.Join(
trimVersion(previousRelease),
constants.InitramfsAsset,
),
),
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", previousRelease),
SourceVersion: previousRelease,
SourceK8sVersion: previousK8sVersion,
TargetInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", stableRelease),
TargetVersion: stableRelease,
TargetK8sVersion: stableK8sVersion,
ControlplaneNodes: DefaultSettings.ControlplaneNodes,
WorkerNodes: DefaultSettings.WorkerNodes,
}
}
// upgradeStableToCurrent upgrades from the stable Talos release to the current version.
func upgradeStableToCurrent() upgradeSpec {
return upgradeSpec{
ShortName: fmt.Sprintf("%s-%s", stableRelease, DefaultSettings.CurrentVersion),
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.KernelAsset)),
SourceInitramfsPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.InitramfsAsset)),
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", stableRelease),
SourceVersion: stableRelease,
SourceK8sVersion: stableK8sVersion,
TargetInstallerImage: fmt.Sprintf(
"%s/%s:%s",
DefaultSettings.TargetInstallImageRegistry,
images.DefaultInstallerImageName,
DefaultSettings.CurrentVersion,
),
TargetVersion: DefaultSettings.CurrentVersion,
TargetK8sVersion: currentK8sVersion,
ControlplaneNodes: DefaultSettings.ControlplaneNodes,
WorkerNodes: DefaultSettings.WorkerNodes,
}
}
// upgradeCurrentToCurrent upgrades the current version to itself.
func upgradeCurrentToCurrent() upgradeSpec {
installerImage := fmt.Sprintf(
"%s/%s:%s",
DefaultSettings.TargetInstallImageRegistry,
images.DefaultInstallerImageName,
DefaultSettings.CurrentVersion,
)
return upgradeSpec{
ShortName: fmt.Sprintf("%s-same-ver", DefaultSettings.CurrentVersion),
SourceKernelPath: helpers.ArtifactPath(constants.KernelAssetWithArch),
SourceInitramfsPath: helpers.ArtifactPath(constants.InitramfsAssetWithArch),
SourceInstallerImage: installerImage,
SourceVersion: DefaultSettings.CurrentVersion,
SourceK8sVersion: currentK8sVersion,
TargetInstallerImage: installerImage,
TargetVersion: DefaultSettings.CurrentVersion,
TargetK8sVersion: currentK8sVersion,
ControlplaneNodes: DefaultSettings.ControlplaneNodes,
WorkerNodes: DefaultSettings.WorkerNodes,
WithEncryption: true,
}
}
// upgradeCurrentToCurrentBios upgrades the current version to itself without UEFI.
func upgradeCurrentToCurrentBios() upgradeSpec {
installerImage := fmt.Sprintf(
"%s/%s:%s",
DefaultSettings.TargetInstallImageRegistry,
images.DefaultInstallerImageName,
DefaultSettings.CurrentVersion,
)
return upgradeSpec{
ShortName: fmt.Sprintf("%s-same-ver-bios", DefaultSettings.CurrentVersion),
SourceDiskImagePath: helpers.ArtifactPath("metal-amd64.raw.zst"),
SourceInstallerImage: installerImage,
SourceVersion: DefaultSettings.CurrentVersion,
SourceK8sVersion: currentK8sVersion,
TargetInstallerImage: installerImage,
TargetVersion: DefaultSettings.CurrentVersion,
TargetK8sVersion: currentK8sVersion,
ControlplaneNodes: DefaultSettings.ControlplaneNodes,
WorkerNodes: DefaultSettings.WorkerNodes,
WithEncryption: true,
WithBios: true,
WithApplyConfig: true,
}
}
// upgradeStableToCurrentPreserveStage upgrades from the stable Talos release to the current version for single-node cluster with preserve and stage.
func upgradeStableToCurrentPreserveStage() upgradeSpec {
return upgradeSpec{
ShortName: fmt.Sprintf("prsrv-stg-%s-%s", stableRelease, DefaultSettings.CurrentVersion),
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.KernelAsset)),
SourceInitramfsPath: helpers.ArtifactPath(filepath.Join(trimVersion(stableRelease), constants.InitramfsAsset)),
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", stableRelease),
SourceVersion: stableRelease,
SourceK8sVersion: stableK8sVersion,
TargetInstallerImage: fmt.Sprintf(
"%s/%s:%s",
DefaultSettings.TargetInstallImageRegistry,
images.DefaultInstallerImageName,
DefaultSettings.CurrentVersion,
),
TargetVersion: DefaultSettings.CurrentVersion,
TargetK8sVersion: currentK8sVersion,
ControlplaneNodes: 1,
WorkerNodes: 0,
UpgradeStage: true,
}
}
// UpgradeSuite ...
type UpgradeSuite struct {
BaseSuite
specGen func() upgradeSpec
spec upgradeSpec
track int
}
// SetupSuite ...
func (suite *UpgradeSuite) SetupSuite() {
// call generate late in the flow, as it needs to pick up settings overridden by test runner
suite.spec = suite.specGen()
suite.T().Logf("upgrade spec = %v", suite.spec)
suite.BaseSuite.SetupSuite()
}
// runE2E runs e2e test on the cluster.
func (suite *UpgradeSuite) runE2E(k8sVersion string) {
if suite.spec.WorkerNodes == 0 {
// no worker nodes, should make masters schedulable
suite.untaint("control-plane-1")
}
suite.BaseSuite.runE2E(k8sVersion)
}
// TestRolling performs rolling upgrade starting with master nodes.
func (suite *UpgradeSuite) TestRolling() {
suite.setupCluster(clusterOptions{
ClusterName: suite.spec.ShortName,
ControlplaneNodes: suite.spec.ControlplaneNodes,
WorkerNodes: suite.spec.WorkerNodes,
SourceKernelPath: suite.spec.SourceKernelPath,
SourceInitramfsPath: suite.spec.SourceInitramfsPath,
SourceDiskImagePath: suite.spec.SourceDiskImagePath,
SourceInstallerImage: suite.spec.SourceInstallerImage,
SourceVersion: suite.spec.SourceVersion,
SourceK8sVersion: suite.spec.SourceK8sVersion,
WithEncryption: suite.spec.WithEncryption,
WithBios: suite.spec.WithBios,
WithApplyConfig: suite.spec.WithApplyConfig,
})
client, err := suite.clusterAccess.Client()
suite.Require().NoError(err)
// verify initial cluster version
suite.assertSameVersionCluster(client, suite.spec.SourceVersion)
options := upgradeOptions{
TargetInstallerImage: suite.spec.TargetInstallerImage,
UpgradeStage: suite.spec.UpgradeStage,
TargetVersion: suite.spec.TargetVersion,
}
// upgrade master nodes
for _, node := range suite.Cluster.Info().Nodes {
if node.Type == machine.TypeInit || node.Type == machine.TypeControlPlane {
suite.upgradeNode(client, node, options)
}
}
// upgrade worker nodes
for _, node := range suite.Cluster.Info().Nodes {
if node.Type == machine.TypeWorker {
suite.upgradeNode(client, node, options)
}
}
// verify final cluster version
suite.assertSameVersionCluster(client, suite.spec.TargetVersion)
// upgrade Kubernetes if required
suite.upgradeKubernetes(suite.spec.SourceK8sVersion, suite.spec.TargetK8sVersion, suite.spec.SkipKubeletUpgrade)
// run e2e test
suite.runE2E(suite.spec.TargetK8sVersion)
}
// SuiteName ...
func (suite *UpgradeSuite) SuiteName() string {
if suite.spec.ShortName == "" {
suite.spec = suite.specGen()
}
return fmt.Sprintf("provision.UpgradeSuite.%s-TR%d", suite.spec.ShortName, suite.track)
}
func init() {
allSuites = append(
allSuites,
&UpgradeSuite{specGen: upgradePreviousToStable, track: 0},
&UpgradeSuite{specGen: upgradeStableToCurrent, track: 1},
&UpgradeSuite{specGen: upgradeCurrentToCurrent, track: 2},
&UpgradeSuite{specGen: upgradeCurrentToCurrentBios, track: 0},
&UpgradeSuite{specGen: upgradeStableToCurrentPreserveStage, track: 1},
)
}