Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cni/cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type NetworkConfig struct {
CniVersion string `json:"cniVersion"`
Name string `json:"name"` // Name is the Network Name.
Type hcn.NetworkType `json:"type"` // As per SPEC, Type is Name of the Binary
Master string `json:"master,omitempty"` // Host interface name to bind the network to
Ipam IpamConfig `json:"ipam"`
DNS cniTypes.DNS `json:"dns"`
OptionalFlags OptionalFlags `json:"optionalFlags"`
Expand Down Expand Up @@ -279,9 +280,14 @@ func (config *NetworkConfig) GetNetworkInfo(podNamespace string) (ninfo *network
Name: config.Name,
Type: config.Type,
Subnets: subnets,
InterfaceName: "",
InterfaceName: config.Master,
DNS: dnsSettings,
}

// Log when master interface is specified
if config.Master != "" {
logrus.Infof("[cni-net] Using master interface '%s' for network '%s'", config.Master, config.Name)
}
if config.AdditionalArgs != nil {
for _, kvp := range config.AdditionalArgs {
if strings.Contains(kvp.Name, "Policy") {
Expand Down
86 changes: 86 additions & 0 deletions cni/cni_master_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright Microsoft Corp.
// All rights reserved.

//go:build windows
// +build windows

package cni

import (
"testing"
)

// TestParseMasterField tests that the master field is properly parsed from CNI config
func TestParseMasterField(t *testing.T) {
// Test with master field present
configWithMaster := `{
"cniVersion": "0.3.0",
"name": "testNetwork",
"type": "nat",
"master": "Ethernet",
"ipam": {
"subnet": "192.168.100.0/24"
}
}`

config, err := ParseNetworkConfig([]byte(configWithMaster))
if err != nil {
t.Fatalf("Failed to parse config with master field: %v", err)
}

if config.Master != "Ethernet" {
t.Errorf("Expected master to be 'Ethernet', got '%s'", config.Master)
}

// Test with master field missing (should be empty string)
configWithoutMaster := `{
"cniVersion": "0.3.0",
"name": "testNetwork",
"type": "nat",
"ipam": {
"subnet": "192.168.100.0/24"
}
}`

config2, err := ParseNetworkConfig([]byte(configWithoutMaster))
if err != nil {
t.Fatalf("Failed to parse config without master field: %v", err)
}

if config2.Master != "" {
t.Errorf("Expected master to be empty when not specified, got '%s'", config2.Master)
}
}

// TestMasterFieldInNetworkInfo tests that the master field is properly propagated to NetworkInfo
func TestMasterFieldInNetworkInfo(t *testing.T) {
config := &NetworkConfig{
CniVersion: "0.3.0",
Name: "testNetwork",
Type: "nat",
Master: "Ethernet",
Ipam: IpamConfig{
Subnet: "192.168.100.0/24",
},
}

networkInfo, err := config.GetNetworkInfo("")
if err != nil {
t.Fatalf("Failed to get network info: %v", err)
}

if networkInfo.InterfaceName != "Ethernet" {
t.Errorf("Expected InterfaceName to be 'Ethernet', got '%s'", networkInfo.InterfaceName)
}

// Test with empty master
config.Master = ""
networkInfo2, err := config.GetNetworkInfo("")
if err != nil {
t.Fatalf("Failed to get network info with empty master: %v", err)
}

if networkInfo2.InterfaceName != "" {
t.Errorf("Expected InterfaceName to be empty when master is empty, got '%s'", networkInfo2.InterfaceName)
}
}