talos/internal/integration/api/platform.go
Andrey Smirnov 8db34624c6
fix: handle correctly changing platform network config
The bug was with incorrect condition: if `activeNetworkConfig` was ever
set to non-nil value, it was stuck with this value forever, despite new
network config being available with `networkConfig`.

In `talosctl dashboard` case, Talos `metal` platform always reports
initial data (before META is available) which doesn't have any network
config, but later on sends updates (if something updates META), so this
bug leads to Talos being stuck with initial empty network config.

Fixes #10787

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
2025-04-24 20:04:46 +04:00

109 lines
3.3 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_api
package api
import (
"context"
"net/netip"
"time"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
v1alpha1runtime "github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
"github.com/siderolabs/talos/internal/integration/base"
"github.com/siderolabs/talos/pkg/machinery/client"
"github.com/siderolabs/talos/pkg/machinery/meta"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
"github.com/siderolabs/talos/pkg/machinery/resources/runtime"
)
// PlatformSuite ...
type PlatformSuite struct {
base.APISuite
ctx context.Context //nolint:containedctx
ctxCancel context.CancelFunc
}
// SuiteName ...
func (suite *PlatformSuite) SuiteName() string {
return "api.PlatformSuite"
}
// SetupTest ...
func (suite *PlatformSuite) SetupTest() {
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 15*time.Second)
}
// TearDownTest ...
func (suite *PlatformSuite) TearDownTest() {
if suite.ctxCancel != nil {
suite.ctxCancel()
}
}
// TestPlatformMetadata verifies platform metadata.
func (suite *PlatformSuite) TestPlatformMetadata() {
node := suite.RandomDiscoveredNodeInternalIP()
ctx := client.WithNode(suite.ctx, node)
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, runtime.PlatformMetadataID, func(md *runtime.PlatformMetadata, asrt *assert.Assertions) {
marshaled, err := resource.MarshalYAML(md)
suite.Require().NoError(err)
yml, err := yaml.Marshal(marshaled)
suite.Require().NoError(err)
suite.T().Logf("platform metadata:\n%s", string(yml))
if md.TypedSpec().Platform == "aws" || md.TypedSpec().Platform == "gcp" {
asrt.NotEmpty(md.TypedSpec().Tags)
}
})
}
// TestMetalPlatformMetadata verifies platform metadata for metal platform.
func (suite *PlatformSuite) TestMetalPlatformMetadata() {
if suite.Cluster == nil || suite.Cluster.Provisioner() != base.ProvisionerQEMU {
suite.T().Skip("skipping platform metal test since provisioner is not qemu")
}
node := suite.RandomDiscoveredNodeInternalIP()
ctx := client.WithNode(suite.ctx, node)
suite.T().Logf("verifying metal platform network config on node %s", node)
// fake external IP attached to the machine
const externalIP = "1.2.3.4"
platformNetworkConfig := v1alpha1runtime.PlatformNetworkConfig{
ExternalIPs: []netip.Addr{
netip.MustParseAddr(externalIP),
},
}
platformNetworkConfigMarshaled, err := yaml.Marshal(platformNetworkConfig)
suite.Require().NoError(err)
suite.Require().NoError(suite.Client.MetaWrite(ctx, meta.MetalNetworkPlatformConfig, platformNetworkConfigMarshaled))
// address should appear on the node
rtestutils.AssertResource(ctx, suite.T(), suite.Client.COSI, "external/"+externalIP+"/32", func(*network.AddressStatus, *assert.Assertions) {})
suite.Require().NoError(suite.Client.MetaDelete(ctx, meta.MetalNetworkPlatformConfig))
// address should be removed
rtestutils.AssertNoResource[*network.AddressStatus](ctx, suite.T(), suite.Client.COSI, "external/"+externalIP)
}
func init() {
allSuites = append(allSuites, new(PlatformSuite))
}