mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-08 07:37:06 +02:00
The issue is not so easy to fix, as GRPC tunnel on/off change requires two different flow for the link (interface): * no tunnel -> Talos link controller should create in-kernel `wireguard` link and no userspace components * tunnel on -> Talos link controller should never create the link, and only adjust WG settings via UAPI, while the actual link is created by the userspace implementation (it's a `tun` device) Transition between those two links is impossible for the link controller to distinguish, as it doesn't know that it has to drop old link and skip creating new one based on the information available. So, instead, use different names for the link in two states: `siderolink` for the kernel flow, and `siderolinktun` for the userspace flow. This fixes the issue of proper link cleanup/re-creation. Add integration tests. Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
116 lines
3.6 KiB
Go
116 lines
3.6 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/url"
|
|
"time"
|
|
|
|
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
|
|
"github.com/cosi-project/runtime/pkg/safe"
|
|
"github.com/cosi-project/runtime/pkg/state"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/siderolabs/talos/internal/integration/base"
|
|
"github.com/siderolabs/talos/pkg/machinery/client"
|
|
siderolinkconfig "github.com/siderolabs/talos/pkg/machinery/config/types/siderolink"
|
|
"github.com/siderolabs/talos/pkg/machinery/resources/siderolink"
|
|
)
|
|
|
|
// SideroLinkSuite ...
|
|
type SideroLinkSuite struct {
|
|
base.APISuite
|
|
|
|
ctx context.Context //nolint:containedctx
|
|
ctxCancel context.CancelFunc
|
|
}
|
|
|
|
// SuiteName ...
|
|
func (suite *SideroLinkSuite) SuiteName() string {
|
|
return "api.SideroLinkSuite"
|
|
}
|
|
|
|
// SetupTest ...
|
|
func (suite *SideroLinkSuite) SetupTest() {
|
|
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 2*time.Minute)
|
|
}
|
|
|
|
// TearDownTest ...
|
|
func (suite *SideroLinkSuite) TearDownTest() {
|
|
if suite.ctxCancel != nil {
|
|
suite.ctxCancel()
|
|
}
|
|
}
|
|
|
|
// TestTunnelSettingFlip enables/disables the tunnel-over-GRPC setting of the link.
|
|
func (suite *SideroLinkSuite) TestTunnelSettingFlip() {
|
|
// pick up a random node to test the SideroLink on, and use it throughout the test
|
|
node := suite.RandomDiscoveredNodeInternalIP()
|
|
|
|
suite.T().Logf("testing SideroLink on node %s", node)
|
|
|
|
// build a Talos API context which is tied to the node
|
|
nodeCtx := client.WithNode(suite.ctx, node)
|
|
|
|
// check if SideroLink is enabled
|
|
sideroLinkConfig, err := safe.StateGetByID[*siderolink.Config](nodeCtx, suite.Client.COSI, siderolink.ConfigID)
|
|
if err != nil {
|
|
if state.IsNotFoundError(err) {
|
|
suite.T().Skip("skipping the test since SideroLink is not enabled")
|
|
}
|
|
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
// assert that siderolink is connected
|
|
rtestutils.AssertResource(nodeCtx, suite.T(), suite.Client.COSI, siderolink.StatusID, func(status *siderolink.Status, asrt *assert.Assertions) {
|
|
asrt.True(status.TypedSpec().Connected, "SideroLink is not connected")
|
|
})
|
|
|
|
apiURL, err := url.Parse(sideroLinkConfig.TypedSpec().APIEndpoint)
|
|
suite.Require().NoError(err)
|
|
|
|
q := apiURL.Query()
|
|
|
|
// flip the tunnel setting
|
|
if sideroLinkConfig.TypedSpec().Tunnel {
|
|
q.Del("grpc_tunnel")
|
|
|
|
suite.T().Log("flipping the tunnel setting to false")
|
|
} else {
|
|
q.Set("grpc_tunnel", "true")
|
|
|
|
suite.T().Log("flipping the tunnel setting to true")
|
|
}
|
|
|
|
apiURL.RawQuery = q.Encode()
|
|
|
|
cfgDocument := siderolinkconfig.NewConfigV1Alpha1()
|
|
cfgDocument.APIUrlConfig.URL = apiURL
|
|
|
|
// patch settings
|
|
suite.PatchMachineConfig(nodeCtx, cfgDocument)
|
|
|
|
// first, the config should be updated
|
|
rtestutils.AssertResource(nodeCtx, suite.T(), suite.Client.COSI, siderolink.ConfigID, func(config *siderolink.Config, asrt *assert.Assertions) {
|
|
asrt.Equal(!sideroLinkConfig.TypedSpec().Tunnel, config.TypedSpec().Tunnel, "SideroLink tunnel setting is not updated")
|
|
})
|
|
|
|
suite.T().Log("configuration updated, waiting for SideroLink to reconnect...")
|
|
|
|
// second, new status should reflect the change
|
|
rtestutils.AssertResource(nodeCtx, suite.T(), suite.Client.COSI, siderolink.StatusID, func(status *siderolink.Status, asrt *assert.Assertions) {
|
|
asrt.True(status.TypedSpec().Connected, "SideroLink is not connected")
|
|
asrt.Equal(!sideroLinkConfig.TypedSpec().Tunnel, status.TypedSpec().GRPCTunnel, "SideroLink tunnel setting is not updated")
|
|
})
|
|
}
|
|
|
|
func init() {
|
|
allSuites = append(allSuites, new(SideroLinkSuite))
|
|
}
|