mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-07 21:51:30 +02:00
Implement a screen for entering/managing the config `${code}` variable. Enable this screen only when the platform is `metal` and there is a `${code}` variable in the `talos.config` kernel cmdline URL query. Additionally, remove the "Delete" button and its functionality from the network config screen to avoid users accidentally deleting PlatformNetworkConfig parts that are not managed by the dashboard. Add some tests for the form data parsing on the network config screen. Remove the unnecessary lock on the summary tab - all updates come from the same goroutine. Closes siderolabs/talos#6993. Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
246 lines
6.0 KiB
Go
246 lines
6.0 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/.
|
|
|
|
package dashboard_test
|
|
|
|
import (
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime"
|
|
"github.com/siderolabs/talos/internal/pkg/dashboard"
|
|
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
|
|
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
|
runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime"
|
|
)
|
|
|
|
func TestEmptyFormData(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{}
|
|
|
|
config, err := formData.ToPlatformNetworkConfig()
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, runtime.PlatformNetworkConfig{}, *config)
|
|
}
|
|
|
|
func TestBaseDataZeroOut(t *testing.T) {
|
|
base := runtime.PlatformNetworkConfig{
|
|
Addresses: []network.AddressSpecSpec{
|
|
{
|
|
LinkName: "foobar",
|
|
},
|
|
},
|
|
Links: []network.LinkSpecSpec{
|
|
{
|
|
Name: "foobar",
|
|
},
|
|
},
|
|
Routes: []network.RouteSpecSpec{
|
|
{
|
|
OutLinkName: "foobar",
|
|
},
|
|
},
|
|
Hostnames: []network.HostnameSpecSpec{
|
|
{
|
|
Hostname: "foobar",
|
|
},
|
|
},
|
|
Resolvers: []network.ResolverSpecSpec{
|
|
{
|
|
DNSServers: []netip.Addr{
|
|
netip.MustParseAddr("1.2.3.4"),
|
|
},
|
|
},
|
|
},
|
|
TimeServers: []network.TimeServerSpecSpec{
|
|
{
|
|
NTPServers: []string{"foobar"},
|
|
},
|
|
},
|
|
Operators: []network.OperatorSpecSpec{
|
|
{
|
|
LinkName: "foobar",
|
|
},
|
|
},
|
|
ExternalIPs: []netip.Addr{
|
|
netip.MustParseAddr("2.3.4.5"),
|
|
},
|
|
Metadata: &runtimeres.PlatformMetadataSpec{
|
|
Platform: "foobar",
|
|
Spot: true,
|
|
},
|
|
}
|
|
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Base: base,
|
|
}
|
|
|
|
config, err := formData.ToPlatformNetworkConfig()
|
|
assert.NoError(t, err)
|
|
|
|
// assert that the fields managed by the form are zeroed out
|
|
assert.Empty(t, config.Addresses)
|
|
assert.Empty(t, config.Links)
|
|
assert.Empty(t, config.Routes)
|
|
assert.Empty(t, config.Hostnames)
|
|
assert.Empty(t, config.Resolvers)
|
|
assert.Empty(t, config.TimeServers)
|
|
assert.Empty(t, config.Operators)
|
|
|
|
// assert that the fields not managed by the form are untouched
|
|
assert.Equal(t, base.ExternalIPs, config.ExternalIPs)
|
|
assert.Equal(t, base.Metadata, config.Metadata)
|
|
}
|
|
|
|
func TestFilledFormNoIface(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Base: runtime.PlatformNetworkConfig{
|
|
Metadata: &runtimeres.PlatformMetadataSpec{
|
|
Platform: "foobar",
|
|
},
|
|
},
|
|
Hostname: "foobar",
|
|
DNSServers: "1.2.3.4 5.6.7.8",
|
|
TimeServers: "a.example.com , b.example.com",
|
|
}
|
|
|
|
config, err := formData.ToPlatformNetworkConfig()
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(
|
|
t,
|
|
runtime.PlatformNetworkConfig{
|
|
Hostnames: []network.HostnameSpecSpec{{
|
|
Hostname: "foobar",
|
|
ConfigLayer: network.ConfigPlatform,
|
|
}},
|
|
Resolvers: []network.ResolverSpecSpec{{
|
|
DNSServers: []netip.Addr{
|
|
netip.MustParseAddr("1.2.3.4"),
|
|
netip.MustParseAddr("5.6.7.8"),
|
|
},
|
|
ConfigLayer: network.ConfigPlatform,
|
|
}},
|
|
TimeServers: []network.TimeServerSpecSpec{
|
|
{
|
|
NTPServers: []string{"a.example.com", "b.example.com"},
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
Metadata: &runtimeres.PlatformMetadataSpec{
|
|
Platform: "foobar",
|
|
},
|
|
},
|
|
*config,
|
|
)
|
|
}
|
|
|
|
func TestFilledFormModeDHCP(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Iface: "eth0",
|
|
Mode: dashboard.ModeDHCP,
|
|
}
|
|
|
|
config, err := formData.ToPlatformNetworkConfig()
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, runtime.PlatformNetworkConfig{
|
|
Links: []network.LinkSpecSpec{
|
|
{
|
|
Name: formData.Iface,
|
|
Logical: false,
|
|
Up: true,
|
|
Type: nethelpers.LinkEther,
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
Operators: []network.OperatorSpecSpec{
|
|
{
|
|
Operator: network.OperatorDHCP4,
|
|
LinkName: formData.Iface,
|
|
RequireUp: true,
|
|
DHCP4: network.DHCP4OperatorSpec{
|
|
RouteMetric: 1024,
|
|
},
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
}, *config)
|
|
}
|
|
|
|
func TestFilledFormModeStaticNoAddresses(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Iface: "eth0",
|
|
Mode: dashboard.ModeStatic,
|
|
}
|
|
|
|
_, err := formData.ToPlatformNetworkConfig()
|
|
assert.ErrorContains(t, err, "no addresses specified")
|
|
}
|
|
|
|
func TestFilledFormModeStaticNoGateway(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Iface: "eth0",
|
|
Mode: dashboard.ModeStatic,
|
|
Addresses: "1.2.3.4/24",
|
|
}
|
|
|
|
_, err := formData.ToPlatformNetworkConfig()
|
|
assert.ErrorContains(t, err, "unable to parse")
|
|
}
|
|
|
|
func TestFilledFormModeStatic(t *testing.T) {
|
|
formData := dashboard.NetworkConfigFormData{
|
|
Iface: "eth42",
|
|
Mode: dashboard.ModeStatic,
|
|
Addresses: "1.2.3.4/24 2.3.4.5/32",
|
|
Gateway: "3.4.5.6",
|
|
}
|
|
|
|
config, err := formData.ToPlatformNetworkConfig()
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, runtime.PlatformNetworkConfig{
|
|
Links: []network.LinkSpecSpec{
|
|
{
|
|
Name: formData.Iface,
|
|
Logical: false,
|
|
Up: true,
|
|
Type: nethelpers.LinkEther,
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
Addresses: []network.AddressSpecSpec{
|
|
{
|
|
Address: netip.MustParsePrefix("1.2.3.4/24"),
|
|
LinkName: formData.Iface,
|
|
Family: nethelpers.FamilyInet4,
|
|
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
{
|
|
Address: netip.MustParsePrefix("2.3.4.5/32"),
|
|
LinkName: formData.Iface,
|
|
Family: nethelpers.FamilyInet4,
|
|
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
Routes: []network.RouteSpecSpec{
|
|
{
|
|
Family: nethelpers.FamilyInet4,
|
|
Gateway: netip.MustParseAddr("3.4.5.6"),
|
|
OutLinkName: "eth42",
|
|
Table: nethelpers.TableMain,
|
|
Scope: nethelpers.ScopeGlobal,
|
|
Type: nethelpers.TypeUnicast,
|
|
Protocol: nethelpers.ProtocolStatic,
|
|
ConfigLayer: network.ConfigPlatform,
|
|
},
|
|
},
|
|
}, *config)
|
|
}
|