Skip to content

Commit c81df6f

Browse files
mcanevetsmira
authored andcommitted
refactor(machined): extract per-interface IPv4 helper in OpenNebula driver
Move the per-interface IPv4 logic from ParseMetadata into a dedicated parseInterfaceIPv4 helper, and add an empty parseInterfaceIPv6 stub. ParseMetadata now delegates all per-interface work to those two helpers plus the existing parseAliases, keeping its own body small. No behaviour change; all existing tests pass. Signed-off-by: Mickaël Canévet <mickael.canevet@proton.ch> Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com> (cherry picked from commit 469db18)
1 parent 501924e commit c81df6f

File tree

2 files changed

+466
-164
lines changed

2 files changed

+466
-164
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
package opennebula_test
6+
7+
import (
8+
"net/netip"
9+
"testing"
10+
11+
"github.com/cosi-project/runtime/pkg/state"
12+
"github.com/cosi-project/runtime/pkg/state/impl/inmem"
13+
"github.com/cosi-project/runtime/pkg/state/impl/namespaced"
14+
"github.com/stretchr/testify/assert"
15+
"github.com/stretchr/testify/require"
16+
17+
"github.com/siderolabs/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/opennebula"
18+
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
19+
"github.com/siderolabs/talos/pkg/machinery/resources/network"
20+
)
21+
22+
const ipv6ContextBase = `ETH0_MAC = "02:00:c0:a8:01:5c"
23+
ETH0_IP = "192.168.1.92"
24+
ETH0_MASK = "255.255.255.0"
25+
NAME = "test"
26+
`
27+
28+
func ipv6Context(extra string) []byte {
29+
return []byte(ipv6ContextBase + extra)
30+
}
31+
32+
func TestParseIPv6Static(t *testing.T) {
33+
t.Parallel()
34+
35+
o := &opennebula.OpenNebula{}
36+
st := state.WrapCore(namespaced.NewState(inmem.Build))
37+
38+
defaultGWRoute := func(gw string, priority uint32) network.RouteSpecSpec {
39+
return network.RouteSpecSpec{
40+
ConfigLayer: network.ConfigPlatform,
41+
Gateway: netip.MustParseAddr(gw),
42+
OutLinkName: "eth0",
43+
Table: nethelpers.TableMain,
44+
Protocol: nethelpers.ProtocolStatic,
45+
Type: nethelpers.TypeUnicast,
46+
Family: nethelpers.FamilyInet6,
47+
Priority: priority,
48+
Scope: nethelpers.ScopeGlobal,
49+
}
50+
}
51+
52+
for _, tc := range []struct {
53+
name string
54+
extra string
55+
wantAddrs []netip.Prefix
56+
wantRoutes []network.RouteSpecSpec
57+
}{
58+
{
59+
name: "static IPv6 address with explicit prefix length",
60+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_PREFIX_LENGTH = \"48\"",
61+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/48")},
62+
},
63+
{
64+
name: "ETH*_IPV6 legacy alias used when ETH*_IP6 absent",
65+
extra: "ETH0_IPV6 = \"2001:db8::1\"",
66+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64")},
67+
},
68+
{
69+
name: "prefix length defaults to 64",
70+
extra: "ETH0_IP6 = \"2001:db8::1\"",
71+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64")},
72+
},
73+
{
74+
name: "explicit prefix length respected",
75+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_PREFIX_LENGTH = \"56\"",
76+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/56")},
77+
},
78+
{
79+
name: "ULA address emitted as second AddressSpecSpec",
80+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_ULA = \"fd00::1\"",
81+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64"), netip.MustParsePrefix("fd00::1/64")},
82+
},
83+
{
84+
name: "IPv6 gateway emits default route with metric 1",
85+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_GATEWAY = \"2001:db8::fffe\"",
86+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64")},
87+
wantRoutes: []network.RouteSpecSpec{defaultGWRoute("2001:db8::fffe", 1)},
88+
},
89+
{
90+
name: "ETH*_GATEWAY6 legacy alias used when ETH*_IP6_GATEWAY absent",
91+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_GATEWAY6 = \"2001:db8::fffe\"",
92+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64")},
93+
wantRoutes: []network.RouteSpecSpec{defaultGWRoute("2001:db8::fffe", 1)},
94+
},
95+
{
96+
name: "ETH*_IP6_METRIC overrides default metric of 1",
97+
extra: "ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_GATEWAY = \"2001:db8::fffe\"\nETH0_IP6_METRIC = \"100\"",
98+
wantAddrs: []netip.Prefix{netip.MustParsePrefix("2001:db8::1/64")},
99+
wantRoutes: []network.RouteSpecSpec{defaultGWRoute("2001:db8::fffe", 100)},
100+
},
101+
{
102+
name: "no IPv6 variables — no IPv6 addresses or routes",
103+
extra: "",
104+
},
105+
} {
106+
t.Run(tc.name, func(t *testing.T) {
107+
t.Parallel()
108+
109+
networkConfig, err := o.ParseMetadata(st, ipv6Context(tc.extra))
110+
require.NoError(t, err)
111+
112+
var ip6Addrs []netip.Prefix
113+
114+
for _, a := range networkConfig.Addresses {
115+
if a.Family == nethelpers.FamilyInet6 {
116+
ip6Addrs = append(ip6Addrs, a.Address)
117+
}
118+
}
119+
120+
assert.Equal(t, tc.wantAddrs, ip6Addrs)
121+
122+
var ip6Routes []network.RouteSpecSpec
123+
124+
for _, r := range networkConfig.Routes {
125+
if r.Family == nethelpers.FamilyInet6 {
126+
ip6Routes = append(ip6Routes, r)
127+
}
128+
}
129+
130+
assert.Equal(t, tc.wantRoutes, ip6Routes)
131+
})
132+
}
133+
}
134+
135+
func TestParseIPv6Errors(t *testing.T) {
136+
t.Parallel()
137+
138+
o := &opennebula.OpenNebula{}
139+
st := state.WrapCore(namespaced.NewState(inmem.Build))
140+
141+
t.Run("malformed IPv6 address returns descriptive error", func(t *testing.T) {
142+
t.Parallel()
143+
144+
ctx := ipv6Context("ETH0_IP6 = \"notanip\"")
145+
146+
_, err := o.ParseMetadata(st, ctx)
147+
require.ErrorContains(t, err, "ETH0")
148+
require.ErrorContains(t, err, "IPv6")
149+
})
150+
151+
t.Run("malformed IPv6 gateway returns descriptive error", func(t *testing.T) {
152+
t.Parallel()
153+
154+
ctx := ipv6Context("ETH0_IP6 = \"2001:db8::1\"\nETH0_IP6_GATEWAY = \"notanip\"")
155+
156+
_, err := o.ParseMetadata(st, ctx)
157+
require.ErrorContains(t, err, "ETH0")
158+
require.ErrorContains(t, err, "gateway")
159+
})
160+
}

0 commit comments

Comments
 (0)