Files
k3s/pkg/agent/flannel/setup_test.go
Richard Hansen 925726c84d flannel: Use custom type for network mode (IPv4, IPv6, dual-stack)
Move the `ipv4` and `ipv6` constants to their own constant
declaration.  This ensures that the `iota` expression for the `ipv4`
constant evaluates to 0, not some arbitrary value.  (`iota` evaluates
to N for the Nth constant in the constant declaration; see
<https://go.dev/ref/spec#Iota>.)  This is also more idiomatic, which
improves readability.

Also switch from incremental integers to bit flags, and use bitwise
operators for checking.  This is more idiomatic (the integer is
treated like a set of booleans), it avoids some code duplication, and
it is necessary to avoid ambiguity.  Consider the following:

    const (
    	ipv4 = iota
    	ipv6
    )

In the above, `ipv4` would have the value 0 and `ipv6` would have the
value 1.  This would make it impossible to distinguish an IPv6-only
stack from a dual-stack configuration because `ipv6` would equal
`ipv4 + ipv6`.  With bit flags this problem doesn't exist.

And put the integer holding the bit flags in a custom type with
convenience methods to improve readability.

Signed-off-by: Richard Hansen <rhansen@rhansen.org>
2025-05-09 12:51:48 -07:00

89 lines
2.7 KiB
Go

package flannel
import (
"net"
"os"
"regexp"
"strings"
"testing"
"github.com/k3s-io/k3s/pkg/daemons/config"
)
func stringToCIDR(s string) []*net.IPNet {
var netCidrs []*net.IPNet
for _, v := range strings.Split(s, ",") {
_, parsed, _ := net.ParseCIDR(v)
netCidrs = append(netCidrs, parsed)
}
return netCidrs
}
func Test_findNetMode(t *testing.T) {
tests := []struct {
name string
args string
wantv4 bool
wantv6 bool
wantErr bool
}{
{"dual-stack", "10.42.0.0/16,2001:cafe:22::/56", true, true, false},
{"dual-stack ipv6 first", "2001:cafe:22::/56,10.42.0.0/16", true, true, false},
{"ipv4 only", "10.42.0.0/16", true, false, false},
{"ipv6 only", "2001:cafe:42:0::/56", false, true, false},
{"empty", "", false, false, true},
{"wrong input", "wrong", false, false, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
netCidrs := stringToCIDR(tt.args)
got, err := findNetMode(netCidrs)
if (err != nil) != tt.wantErr {
t.Fatalf("got error %v, want %v", err, tt.wantErr)
}
if gotv4 := got.IPv4Enabled(); gotv4 != tt.wantv4 {
t.Errorf("got ipv4 %v, want %v", gotv4, tt.wantv4)
}
if gotv6 := got.IPv6Enabled(); gotv6 != tt.wantv6 {
t.Errorf("got ipv6 %v, want %v", gotv6, tt.wantv6)
}
})
}
}
func Test_createFlannelConf(t *testing.T) {
tests := []struct {
name string
args string
wantConfig []string
wantErr bool
}{
{"dual-stack", "10.42.0.0/16,2001:cafe:22::/56", []string{"\"Network\": \"10.42.0.0/16\"", "\"IPv6Network\": \"2001:cafe:22::/56\"", "\"EnableIPv6\": true"}, false},
{"ipv4 only", "10.42.0.0/16", []string{"\"Network\": \"10.42.0.0/16\"", "\"IPv6Network\": \"::/0\"", "\"EnableIPv6\": false"}, false},
}
var containerd = config.Containerd{}
for _, tt := range tests {
var agent = config.Agent{}
agent.ClusterCIDR = stringToCIDR(tt.args)[0]
agent.ClusterCIDRs = stringToCIDR(tt.args)
var nodeConfig = &config.Node{Docker: false, ContainerRuntimeEndpoint: "", SELinux: false, FlannelBackend: "vxlan", FlannelConfFile: "test_file", FlannelConfOverride: false, FlannelIface: nil, Containerd: containerd, Images: "", AgentConfig: agent, Token: "", ServerHTTPSPort: 0}
t.Run(tt.name, func(t *testing.T) {
if err := createFlannelConf(nodeConfig); (err != nil) != tt.wantErr {
t.Errorf("createFlannelConf() error = %v, wantErr %v", err, tt.wantErr)
}
data, err := os.ReadFile("test_file")
if err != nil {
t.Errorf("Something went wrong when reading the flannel config file")
}
for _, config := range tt.wantConfig {
isExist, _ := regexp.Match(config, data)
if !isExist {
t.Errorf("Config is wrong, %s is not present", config)
}
}
})
}
}