Skip to content

Commit

Permalink
Add unit tests for default network creation.
Browse files Browse the repository at this point in the history
Signed-off-by: Nashwan Azhari <[email protected]>
  • Loading branch information
aznashwan committed Dec 5, 2022
1 parent 41cdacf commit fbcd366
Showing 1 changed file with 167 additions and 0 deletions.
167 changes: 167 additions & 0 deletions pkg/netutil/netutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,44 @@
package netutil

import (
"bytes"
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"testing"
"text/template"

ncdefaults "github.com/containerd/nerdctl/pkg/defaults"
"github.com/containerd/nerdctl/pkg/labels"
"github.com/containerd/nerdctl/pkg/rootlessutil"
"github.com/containerd/nerdctl/pkg/testutil"

"gotest.tools/v3/assert"
)

const preExistingNetworkConfigTemplate = `
{
"cniVersion": "0.2.0",
"name": "{{ .network_name }}",
"type": "nat",
"master": "Ethernet",
"ipam": {
"subnet": "{{ .subnet }}",
"routes": [
{
"GW": "{{ .gateway }}"
}
]
},
"capabilities": {
"portMappings": true,
"dns": true
}
}
`

func TestParseIPAMRange(t *testing.T) {
t.Parallel()
type testCase struct {
Expand Down Expand Up @@ -97,3 +129,138 @@ func TestParseIPAMRange(t *testing.T) {
}
}
}

// Tests whether nerdctl properly creates the default network when required.
func TestDefaultNetworkCreation(t *testing.T) {
if rootlessutil.IsRootless() {
t.Skip("must be superuser to create default network for this test")
}

// To prevent subnet collisions when attempting to recreate the default network
// in the isolated CNI config dir we'll be using, we must first delete
// the network in the default CNI config dir.
defaultCniEnv := CNIEnv{
Path: ncdefaults.CNIPath(),
NetconfPath: ncdefaults.CNINetConfPath(),
}
defaultNet, err := defaultCniEnv.GetDefaultNetworkConfig()
assert.NilError(t, err)
if defaultNet != nil {
assert.NilError(t, defaultCniEnv.RemoveNetwork(defaultNet))
}

// We create a tempdir for the CNI conf path to ensure an empty env for this test.
cniConfTestDir := t.TempDir()
cniEnv := CNIEnv{
Path: ncdefaults.CNIPath(),
NetconfPath: cniConfTestDir,
}
// Ensure no default network config is not present.
defaultNetConf, err := cniEnv.GetDefaultNetworkConfig()
assert.NilError(t, err)
assert.Assert(t, defaultNetConf == nil)

// Attempt to create the default network.
err = cniEnv.ensureDefaultNetworkConfig()
assert.NilError(t, err)

// Ensure no default network config is present now.
defaultNetConf, err = cniEnv.GetDefaultNetworkConfig()
assert.NilError(t, err)
assert.Assert(t, defaultNetConf != nil)

// Check network config file present.
stat, err := os.Stat(defaultNetConf.File)
assert.NilError(t, err)
firstConfigModTime := stat.ModTime()

// Check default network label present.
assert.Assert(t, defaultNetConf.NerdctlLabels != nil)
lstr, ok := (*defaultNetConf.NerdctlLabels)[labels.NerdctlDefaultNetwork]
assert.Assert(t, ok)
boolv, err := strconv.ParseBool(lstr)
assert.NilError(t, err)
assert.Assert(t, boolv)

// Ensure network isn't created twice or accidentally re-created.
err = cniEnv.ensureDefaultNetworkConfig()
assert.NilError(t, err)

// Check for any other network config files.
files := []os.FileInfo{}
walkF := func(p string, info os.FileInfo, err error) error {
files = append(files, info)
return nil
}
err = filepath.Walk(cniConfTestDir, walkF)
assert.NilError(t, err)
assert.Assert(t, len(files) == 2) // files[0] is the entry for '.'
assert.Assert(t, filepath.Join(cniConfTestDir, files[1].Name()) == defaultNetConf.File)
assert.Assert(t, firstConfigModTime == files[1].ModTime())
}

// Tests whether nerdctl skips the creation of the default network if a
// network bearing the default network name already exists in a
// non-nerdctl-managed network config file.
func TestNetworkWithDefaultNameAlreadyExists(t *testing.T) {
// We create a tempdir for the CNI conf path to ensure an empty env for this test.
cniConfTestDir := t.TempDir()
cniEnv := CNIEnv{
Path: t.TempDir(), // irrelevant for this test
NetconfPath: cniConfTestDir,
}

// Ensure no default network config is not present.
defaultNetConf, err := cniEnv.GetDefaultNetworkConfig()
assert.NilError(t, err)
assert.Assert(t, defaultNetConf == nil)

// Manually define and write a network config file.
values := map[string]string{
"network_name": DefaultNetworkName,
"subnet": "10.7.1.1/24",
"gateway": "10.7.1.1",
}
tpl, err := template.New("test").Parse(preExistingNetworkConfigTemplate)
assert.NilError(t, err)
buf := &bytes.Buffer{}
assert.NilError(t, tpl.ExecuteTemplate(buf, "test", values))

// Filename is irrelevant as long as it's not nerdctl's.
testConfFile := filepath.Join(cniConfTestDir, fmt.Sprintf("%s.conf", testutil.Identifier(t)))
err = os.WriteFile(testConfFile, buf.Bytes(), 0600)
assert.NilError(t, err)

// Check network is detected.
netConfs, err := cniEnv.NetworkList()
assert.NilError(t, err)
assert.Assert(t, len(netConfs) > 0)

var listedDefaultNetConf *NetworkConfig
for _, netConf := range netConfs {
if netConf.Name == DefaultNetworkName {
listedDefaultNetConf = netConf
break
}
}
assert.Assert(t, listedDefaultNetConf != nil)

defaultNetConf, err = cniEnv.GetDefaultNetworkConfig()
assert.NilError(t, err)
assert.Assert(t, defaultNetConf != nil)
assert.Assert(t, defaultNetConf.File == testConfFile)

err = cniEnv.ensureDefaultNetworkConfig()
assert.NilError(t, err)

netConfs, err = cniEnv.NetworkList()
assert.NilError(t, err)
defaultNamedNetworksFileDefinitions := []string{}
for _, netConf := range netConfs {
if netConf.Name == DefaultNetworkName {
defaultNamedNetworksFileDefinitions = append(defaultNamedNetworksFileDefinitions, netConf.File)
}
}
assert.Assert(t, len(defaultNamedNetworksFileDefinitions) == 1)
assert.Assert(t, defaultNamedNetworksFileDefinitions[0] == testConfFile)
}

0 comments on commit fbcd366

Please sign in to comment.