Skip to content
Merged
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
12 changes: 9 additions & 3 deletions cni/network/network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net"
"net/netip"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -154,9 +155,14 @@ func (plugin *NetPlugin) getNetworkName(netNs string, ipamAddResult *IPAMAddResu
// This will happen during ADD call
if ipamAddResult != nil && ipamAddResult.ncResponse != nil {
// networkName will look like ~ azure-vlan1-172-28-1-0_24
subnet := ipamAddResult.ipv4Result.IPs[0].Address
networkName := strings.Replace(subnet.String(), ".", "-", -1)
networkName = strings.Replace(networkName, "/", "_", -1)
ipAddrNet := ipamAddResult.ipv4Result.IPs[0].Address
prefix, err := netip.ParsePrefix(ipAddrNet.String())
if err != nil {
log.Printf("Error parsing %s network CIDR: %v.", ipAddrNet.String(), err)
return "", errors.Wrapf(err, "cns returned invalid CIDR %s", ipAddrNet.String())
}
networkName := strings.ReplaceAll(prefix.Masked().String(), ".", "-")
networkName = strings.ReplaceAll(networkName, "/", "_")
networkName = fmt.Sprintf("%s-vlan%v-%v", nwCfg.Name, ipamAddResult.ncResponse.MultiTenancyInfo.ID, networkName)
return networkName, nil
}
Expand Down
198 changes: 198 additions & 0 deletions cni/network/network_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,201 @@ func TestDSRPolciy(t *testing.T) {
})
}
}

func TestGetNetworkNameFromCNS(t *testing.T) {
plugin, _ := cni.NewPlugin("name", "0.3.0")
tests := []struct {
name string
plugin *NetPlugin
netNs string
nwCfg *cni.NetworkConfig
ipamAddResult *IPAMAddResult
want string
wantErr bool
}{
{
name: "Get Network Name from CNS with correct CIDR",
plugin: &NetPlugin{
Plugin: plugin,
nm: network.NewMockNetworkmanager(),
ipamInvoker: NewMockIpamInvoker(false, false, false),
report: &telemetry.CNIReport{},
tb: &telemetry.TelemetryBuffer{},
},
netNs: "net",
nwCfg: &cni.NetworkConfig{
CNIVersion: "0.3.0",
Name: "azure",
MultiTenancy: true,
},
ipamAddResult: &IPAMAddResult{
ncResponse: &cns.GetNetworkContainerResponse{
MultiTenancyInfo: cns.MultiTenancyInfo{
ID: 1,
},
},
ipv4Result: &cniTypesCurr.Result{
IPs: []*cniTypesCurr.IPConfig{
{
Address: net.IPNet{
IP: net.ParseIP("10.240.0.5"),
Mask: net.CIDRMask(24, 32),
},
},
},
},
},
want: "azure-vlan1-10-240-0-0_24",
wantErr: false,
},
{
name: "Get Network Name from CNS with malformed CIDR #1",
plugin: &NetPlugin{
Plugin: plugin,
nm: network.NewMockNetworkmanager(),
ipamInvoker: NewMockIpamInvoker(false, false, false),
report: &telemetry.CNIReport{},
tb: &telemetry.TelemetryBuffer{},
},
netNs: "net",
nwCfg: &cni.NetworkConfig{
CNIVersion: "0.3.0",
Name: "azure",
MultiTenancy: true,
},
ipamAddResult: &IPAMAddResult{
ncResponse: &cns.GetNetworkContainerResponse{
MultiTenancyInfo: cns.MultiTenancyInfo{
ID: 1,
},
},
ipv4Result: &cniTypesCurr.Result{
IPs: []*cniTypesCurr.IPConfig{
{
Address: net.IPNet{
IP: net.ParseIP(""),
Mask: net.CIDRMask(24, 32),
},
},
},
},
},
want: "",
wantErr: true,
},
{
name: "Get Network Name from CNS with malformed CIDR #2",
plugin: &NetPlugin{
Plugin: plugin,
nm: network.NewMockNetworkmanager(),
ipamInvoker: NewMockIpamInvoker(false, false, false),
report: &telemetry.CNIReport{},
tb: &telemetry.TelemetryBuffer{},
},
netNs: "net",
nwCfg: &cni.NetworkConfig{
CNIVersion: "0.3.0",
Name: "azure",
MultiTenancy: true,
},
ipamAddResult: &IPAMAddResult{
ncResponse: &cns.GetNetworkContainerResponse{
MultiTenancyInfo: cns.MultiTenancyInfo{
ID: 1,
},
},
ipv4Result: &cniTypesCurr.Result{
IPs: []*cniTypesCurr.IPConfig{
{
Address: net.IPNet{
IP: net.ParseIP("10.0.00.6"),
Mask: net.CIDRMask(24, 32),
},
},
},
},
},
want: "",
wantErr: true,
},
{
name: "Get Network Name from CNS without NetNS",
plugin: &NetPlugin{
Plugin: plugin,
nm: network.NewMockNetworkmanager(),
ipamInvoker: NewMockIpamInvoker(false, false, false),
report: &telemetry.CNIReport{},
tb: &telemetry.TelemetryBuffer{},
},
netNs: "",
nwCfg: &cni.NetworkConfig{
CNIVersion: "0.3.0",
Name: "azure",
MultiTenancy: true,
},
ipamAddResult: &IPAMAddResult{
ncResponse: &cns.GetNetworkContainerResponse{
MultiTenancyInfo: cns.MultiTenancyInfo{
ID: 1,
},
},
ipv4Result: &cniTypesCurr.Result{
IPs: []*cniTypesCurr.IPConfig{
{
Address: net.IPNet{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(24, 32),
},
},
},
},
},
want: "",
wantErr: true,
},
{
name: "Get Network Name from CNS without multitenancy",
plugin: &NetPlugin{
Plugin: plugin,
nm: network.NewMockNetworkmanager(),
ipamInvoker: NewMockIpamInvoker(false, false, false),
report: &telemetry.CNIReport{},
tb: &telemetry.TelemetryBuffer{},
},
netNs: "azure",
nwCfg: &cni.NetworkConfig{
CNIVersion: "0.3.0",
Name: "azure",
MultiTenancy: false,
},
ipamAddResult: &IPAMAddResult{
ncResponse: &cns.GetNetworkContainerResponse{},
ipv4Result: &cniTypesCurr.Result{
IPs: []*cniTypesCurr.IPConfig{
{
Address: net.IPNet{
IP: net.ParseIP("10.0.0.6"),
Mask: net.CIDRMask(24, 32),
},
},
},
},
},
want: "azure",
wantErr: false,
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
networkName, err := tt.plugin.getNetworkName(tt.netNs, tt.ipamAddResult, tt.nwCfg)
Copy link
Contributor

@vipul-21 vipul-21 Sep 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to cover the error case scenario as well ? Since this test case is checking the happy path right now. Want to understand the code coverage aspect we take into consideration while writing these tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point we only wanted to make sure that we're producing correct CIDR when the CNS response is valid. Seems that the failure path is not that critical for unit test.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking the failure cases is absolutely critical in unit tests, come on. You should at least be testing that the input validation that you added correctly returns the error that you added when the input is invalid. How else do you know it rejects bad inputs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the unit test that was asked for this particular case. Yes, in general unit test is critical for non-happy paths. I didn't consider it critical here, since I was informed malformed CIDR is not reaching to this function. Nevertheless, I will add a test case for malformed CIDR since it is the only error check that I have added.

if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.want, networkName)
}
})
}
}