diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml new file mode 100644 index 00000000..9f472483 --- /dev/null +++ b/.github/workflows/fuzz.yml @@ -0,0 +1,23 @@ +name: fuzz-tests +on: + schedule: + - cron: "37 4 * * 0" + pull_request: + paths: + - '**fuzz.yml' + +permissions: + contents: read + +jobs: + fuzz-tests: + name: fuzz-tests + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: 1.20.1 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: make fuzz + run: make fuzz diff --git a/Makefile b/Makefile index 3986fe3a..5d198054 100644 --- a/Makefile +++ b/Makefile @@ -47,11 +47,16 @@ testpmd: @$(IMAGE_BUILDER) build -t $(IMAGE_REGISTRY)testpmd:latest -f ./docker/testpmd/Dockerfile ./docker/testpmd/ @$(IMAGE_BUILDER) push $(IMAGE_REGISTRY)testpmd:latest -unit-test: +build-test-container: @$(IMAGE_BUILDER) rm -f userspacecni-unittest @$(IMAGE_BUILDER) build . -f ./docker/userspacecni/Dockerfile.unittest -t userspacecni-unittest:latest @$(IMAGE_BUILDER) run -m 100g --privileged -v ./examples/sample-vpp-host-config/startup.conf:/etc/vpp/startup.conf --name userspacecni-unittest -itd userspacecni-unittest:latest @$(IMAGE_BUILDER) cp userspacecni-unittest:/root/userspace-cni-network-plugin/cnivpp ./ + +unit-test: build-test-container @$(IMAGE_BUILDER) exec userspacecni-unittest bash -c "go test ./cnivpp/ -v -cover" @$(IMAGE_BUILDER) rm -f userspacecni-unittest - \ No newline at end of file + +fuzz: build-test-container + @$(IMAGE_BUILDER) exec userspacecni-unittest bash -c "cd ./cnivpp/test; go test -fuzz=FuzzLoadNetConf -v -fuzztime 120s" + @$(IMAGE_BUILDER) rm -f userspacecni-unittest diff --git a/cnivpp/cnivpp_test.go b/cnivpp/cnivpp_test.go index a54af7f5..6b0f68d6 100644 --- a/cnivpp/cnivpp_test.go +++ b/cnivpp/cnivpp_test.go @@ -8,62 +8,17 @@ import ( "path/filepath" "testing" - "github.com/containernetworking/cni/pkg/skel" current "github.com/containernetworking/cni/pkg/types/100" - "github.com/google/uuid" "github.com/intel/userspace-cni-network-plugin/pkg/types" + "github.com/intel/userspace-cni-network-plugin/userspace/testdata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - apitypes "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/fake" ) -func GetTestPod(sharedDir string) *v1.Pod { - id, _ := uuid.NewUUID() - pod := &v1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - UID: apitypes.UID(id.String()), - Name: fmt.Sprintf("pod-%v", id[:8]), - Namespace: fmt.Sprintf("namespace-%v", id[:8]), - }, - } - if sharedDir != "" { - pod.Spec.Volumes = append(pod.Spec.Volumes, - v1.Volume{ - Name: "shared-dir", - VolumeSource: v1.VolumeSource{ - HostPath: &v1.HostPathVolumeSource{ - Path: sharedDir, - }, - }, - }) - pod.Spec.Containers = append(pod.Spec.Containers, - v1.Container{ - Name: "container", - VolumeMounts: []v1.VolumeMount{{Name: "shared-dir", MountPath: sharedDir}}, - }) - } - return pod -} - -func GetTestArgs() *skel.CmdArgs { - id, _ := uuid.NewUUID() - return &skel.CmdArgs{ - ContainerID: id.String(), - IfName: fmt.Sprintf("eth%v", int(id[7])), - StdinData: []byte("{}"), - } -} - func TestGetMemifSocketfileName(t *testing.T) { t.Run("get Memif Socker File Name", func(t *testing.T) { - args := GetTestArgs() + args := testdata.GetTestArgs() sharedDir, dirErr := os.MkdirTemp("/tmp", "test-cniovs-") require.NoError(t, dirErr, "Can't create temporary directory") @@ -83,14 +38,14 @@ func TestGetMemifSocketfileName(t *testing.T) { func TestAddOnContainer(t *testing.T) { t.Run("save container data to file", func(t *testing.T) { var result *current.Result - args := GetTestArgs() + args := testdata.GetTestArgs() cniVpp := CniVpp{} sharedDir, dirErr := os.MkdirTemp("/tmp", "test-cniovs-") require.NoError(t, dirErr, "Can't create temporary directory") defer os.RemoveAll(sharedDir) - pod := GetTestPod(sharedDir) + pod := testdata.GetTestPod(sharedDir) resPod, resErr := cniVpp.AddOnContainer(&types.NetConf{}, args, nil, sharedDir, pod, result) assert.NoError(t, resErr, "Unexpected error") assert.Equal(t, pod, resPod, "Unexpected change of pod data") @@ -101,7 +56,7 @@ func TestAddOnContainer(t *testing.T) { func TestDelOnContainer(t *testing.T) { t.Run("remove container configuration", func(t *testing.T) { - args := GetTestArgs() + args := testdata.GetTestArgs() cniVpp := CniVpp{} sharedDir, dirErr := os.MkdirTemp("/tmp", "test-cniovs-") @@ -220,13 +175,13 @@ func TestAddOnHost(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var result *current.Result - args := GetTestArgs() + args := testdata.GetTestArgs() sharedDir, dirErr := os.MkdirTemp("/tmp", "test-cnivpp-") require.NoError(t, dirErr, "Can't create temporary directory") defer os.RemoveAll(sharedDir) - pod := GetTestPod(sharedDir) + pod := testdata.GetTestPod(sharedDir) kubeClient := fake.NewSimpleClientset(pod) err := cniVpp.AddOnHost(tc.netConf, args, kubeClient, sharedDir, result) @@ -294,14 +249,14 @@ func TestDelFromHost(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - args := GetTestArgs() + args := testdata.GetTestArgs() sharedDir, dirErr := os.MkdirTemp("/tmp", "test-cnivpp-") require.NoError(t, dirErr, "Can't create temporary directory") defer os.RemoveAll(sharedDir) var result *current.Result - pod := GetTestPod(sharedDir) + pod := testdata.GetTestPod(sharedDir) kubeClient := fake.NewSimpleClientset(pod) _ = cniVpp.AddOnHost(tc.netConf, args, kubeClient, sharedDir, result) diff --git a/cnivpp/test/cni_test.go b/cnivpp/test/cni_test.go new file mode 100644 index 00000000..8b3d039c --- /dev/null +++ b/cnivpp/test/cni_test.go @@ -0,0 +1,84 @@ +/* + * Copyright(c) 2022 Intel Corporation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fuzz + +import ( + "strings" + "testing" + + "github.com/intel/userspace-cni-network-plugin/userspace/cni" +) + +func FuzzLoadNetConf(f *testing.F) { + + seed := ` + { + "cniVersion": "0.3.1", + "type": "userspace", + "name": "userspace-ovs-net-1", + "kubeconfig": "/etc/cni/net.d/multus.d/multus.kubeconfig", + "logFile": "/var/log/userspace-ovs-net-1-cni.log", + "logLevel": "debug", + "host": { + "engine": "ovs-dpdk", + "iftype": "vhostuser", + "netType": "bridge", + "vhost": { + "mode": "client" + }, + "bridge": { + "bridgeName": "br-4" + } + }, + "container": { + "engine": "ovs-dpdk", + "iftype": "vhostuser", + "netType": "interface", + "vhost": { + "mode": "server" + } + }, + "ipam": { + "type": "host-local", + "subnet": "10.56.217.0/24", + "rangeStart": "10.56.217.131", + "rangeEnd": "10.56.217.190", + "routes": [ + { + "dst": "0.0.0.0/0" + } + ], + "gateway": "10.56.217.1" + } + } + ` + + f.Add([]byte(seed)) + + f.Fuzz(func(t *testing.T, fcfg []byte) { + _, err := cni.LoadNetConf(fcfg) + if err != nil { + if strings.Contains(err.Error(), "failed to load netconf:") { + return + } else { + t.Errorf("Error: %s, for input %s", err.Error(), string(fcfg)) + } + + } else { + return + } + }) +} diff --git a/go.mod b/go.mod index 462ff4fa..23d5893a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.4.0 github.com/go-logfmt/logfmt v0.6.0 - github.com/google/uuid v1.5.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 @@ -32,6 +31,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/imdario/mergo v0.3.6 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -44,11 +44,12 @@ require ( github.com/safchain/ethtool v0.3.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/vishvananda/netns v0.0.4 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.16.1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 2fb4c582..cbd1ec80 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -169,14 +169,14 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -184,7 +184,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/userspace/userspace.go b/userspace/cni/cni.go similarity index 84% rename from userspace/userspace.go rename to userspace/cni/cni.go index 5a5b82d1..fd03e936 100644 --- a/userspace/userspace.go +++ b/userspace/cni/cni.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package main +package cni import ( "encoding/json" @@ -27,7 +27,6 @@ import ( "github.com/containernetworking/cni/pkg/skel" cnitypes "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" - cniSpecVersion "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ipam" "github.com/containernetworking/plugins/pkg/ns" @@ -43,10 +42,6 @@ import ( _ "github.com/vishvananda/netlink" ) -var version = "master@git" -var commit = "unknown commit" -var date = "unknown date" - func init() { // this ensures that main runs only on main thread (thread group leader). // since namespace ops (unshare, setns) are done for a single thread, we @@ -54,17 +49,8 @@ func init() { runtime.LockOSThread() } -// -// Local functions -// - -func printVersionString() string { - return fmt.Sprintf("userspace-cni-network-plugin version:%s, commit:%s, date:%s", - version, commit, date) -} - -// loadNetConf() - Unmarshall the inputdata into the NetConf Structure -func loadNetConf(bytes []byte) (*types.NetConf, error) { +// LoadNetConf() - Unmarshall the inputdata into the NetConf Structure +func LoadNetConf(bytes []byte) (*types.NetConf, error) { netconf := &types.NetConf{} if err := json.Unmarshal(bytes, netconf); err != nil { return nil, fmt.Errorf("failed to load netconf: %v", err) @@ -104,7 +90,7 @@ func loadNetConf(bytes []byte) (*types.NetConf, error) { return netconf, nil } -func getPodAndSharedDir(netConf *types.NetConf, +func GetPodAndSharedDir(netConf *types.NetConf, args *skel.CmdArgs, kubeClient kubernetes.Interface) (kubernetes.Interface, *v1.Pod, string, error) { @@ -159,7 +145,7 @@ func getPodAndSharedDir(netConf *types.NetConf, return kubeClient, pod, sharedDir, err } -func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { +func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { var netConf *types.NetConf var containerEngine string @@ -167,7 +153,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac ovs := cniovs.CniOvs{} // Convert the input bytestream into local NetConf structure - netConf, err := loadNetConf(args.StdinData) + netConf, err := LoadNetConf(args.StdinData) logging.Infof("cmdAdd: ENTER (AFTER LOAD) - Container %s Iface %s", args.ContainerID[:12], args.IfName) logging.Verbosef(" Args=%v netConf=%v, exec=%v, kubeClient%v", @@ -196,7 +182,7 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac // Retrieve the "SharedDir", directory to create the socketfile in. // Save off kubeClient and pod for later use if needed. - kubeClient, pod, sharedDir, err := getPodAndSharedDir(netConf, args, kubeClient) + kubeClient, pod, sharedDir, err := GetPodAndSharedDir(netConf, args, kubeClient) if err != nil { _ = logging.Errorf("cmdAdd: Unable to determine \"SharedDir\" - %v", err) return err @@ -283,9 +269,9 @@ func cmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac return cnitypes.PrintResult(result, current.ImplementedSpecVersion) } -func cmdGet(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { +func CmdGet(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { /* - netConf, err := loadNetConf(args.StdinData) + netConf, err := LoadNetConf(args.StdinData) logging.Infof("cmdGet: (AFTER LOAD) - Container %s Iface %s", args.ContainerID[:12], args.IfName) logging.Verbosef(" Args=%v netConf=%v, exec=%v, kubeClient%v", @@ -302,7 +288,7 @@ func cmdGet(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac return nil } -func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { +func CmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface) error { var netConf *types.NetConf var containerEngine string @@ -310,7 +296,7 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac ovs := cniovs.CniOvs{} // Convert the input bytestream into local NetConf structure - netConf, err := loadNetConf(args.StdinData) + netConf, err := LoadNetConf(args.StdinData) logging.Infof("cmdDel: ENTER (AFTER LOAD) - Container %s Iface %s", args.ContainerID[:12], args.IfName) logging.Verbosef(" Args=%v netConf=%v, exec=%v, kubeClient%v", @@ -323,7 +309,7 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac // Retrieve the "SharedDir", directory to create the socketfile in. // Save off kubeClient and pod for later use if needed. - _, pod, sharedDir, err := getPodAndSharedDir(netConf, args, kubeClient) + _, pod, sharedDir, err := GetPodAndSharedDir(netConf, args, kubeClient) if err != nil { _ = logging.Errorf("cmdDel: Unable to determine \"SharedDir\" - %v", err) return err @@ -400,36 +386,3 @@ func cmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interfac return err } - -func main() { - // Init command line flags to clear vendored packages' one, especially in init() - //flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) - - // add version flag - //versionOpt := false - //flag.BoolVar(&versionOpt, "version", false, "Show application version") - //flag.BoolVar(&versionOpt, "v", false, "Show application version") - //flag.Parse() - //if versionOpt == true { - // fmt.Printf("%s\n", printVersionString()) - // return - //} - - // Extend the cmdAdd(), cmdGet() and cmdDel() functions to take - // 'exec invoke.Exec' and 'kubeClient k8s.KubeClient' as input - // parameters. They are passed in as nill from here, but unit test - // code can then call these functions directly and fake out a - // Kubernetes Client. - skel.PluginMain( - func(args *skel.CmdArgs) error { - return cmdAdd(args, nil, nil) - }, - func(args *skel.CmdArgs) error { - return cmdGet(args, nil, nil) - }, - func(args *skel.CmdArgs) error { - return cmdDel(args, nil, nil) - }, - cniSpecVersion.All, - "CNI plugin that manages DPDK based interfaces") -} diff --git a/userspace/main.go b/userspace/main.go new file mode 100644 index 00000000..7f4dbb8d --- /dev/null +++ b/userspace/main.go @@ -0,0 +1,40 @@ +/* + * Copyright(c) 2022 Intel Corporation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package main + +import ( + "github.com/containernetworking/cni/pkg/skel" + cniversion "github.com/containernetworking/cni/pkg/version" + "github.com/intel/userspace-cni-network-plugin/userspace/cni" +) + +// args *skel.CmdArgs, exec invoke.Exec, kubeClient kubernetes.Interface +func main() { + skel.PluginMain( + + func(args *skel.CmdArgs) error { + err := cni.CmdAdd(args, nil, nil) + if err != nil { + return err + } + return nil + }, + func(args *skel.CmdArgs) error { + return cni.CmdGet(args, nil, nil) + }, + func(args *skel.CmdArgs) error { return cni.CmdDel(args, nil, nil) }, + cniversion.All, "USERSPACE CNI Plugin") +} diff --git a/userspace/userspace_test.go b/userspace/userspace_test.go index d5f249b2..d54fe768 100644 --- a/userspace/userspace_test.go +++ b/userspace/userspace_test.go @@ -29,6 +29,7 @@ import ( "github.com/containernetworking/plugins/pkg/testutils" "github.com/intel/userspace-cni-network-plugin/cniovs" "github.com/intel/userspace-cni-network-plugin/pkg/types" + "github.com/intel/userspace-cni-network-plugin/userspace/cni" "github.com/intel/userspace-cni-network-plugin/userspace/testdata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -36,16 +37,6 @@ import ( "k8s.io/client-go/kubernetes/fake" ) -const verString = "userspace-cni-network-plugin version:%s, commit:%s, date:%s" - -func TestPrintVersionString(t *testing.T) { - t.Run("verify version string", func(t *testing.T) { - exp := fmt.Sprintf(verString, version, commit, date) - out := printVersionString() - assert.Equal(t, exp, out, "Version string mismatch") - }) -} - func TestLoadNetConf(t *testing.T) { testCases := []struct { name string @@ -112,14 +103,14 @@ func TestLoadNetConf(t *testing.T) { t.Run(tc.name, func(t *testing.T) { var netConf *types.NetConf - // capture stderror messages from loadNetConf + // capture stderror messages from LoadNetConf stdR, stdW, stdErr := os.Pipe() if stdErr != nil { t.Fatal("Can't capture stderr") } origStdErr := os.Stderr os.Stderr = stdW - netConf, err := loadNetConf([]byte(tc.netConfStr)) + netConf, err := cni.LoadNetConf([]byte(tc.netConfStr)) os.Stderr = origStdErr stdW.Close() var buf bytes.Buffer @@ -213,7 +204,7 @@ func TestGetPodAndSharedDir(t *testing.T) { args.Args = fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", tc.pod.Name, tc.pod.Namespace) } - resClient, resPod, sharedDir, err := getPodAndSharedDir(tc.netConf, args, kubeClient) + resClient, resPod, sharedDir, err := cni.GetPodAndSharedDir(tc.netConf, args, kubeClient) assert.NoError(t, err, "Unexpected error") assert.Equal(t, tc.expSharedDir, sharedDir, "Unexpected sharedDir returned") assert.Equal(t, tc.pod, resPod, "Unexpected pod returned") @@ -345,7 +336,7 @@ func TestCmdAdd(t *testing.T) { } origStdout := os.Stdout os.Stdout = stdW - err := cmdAdd(args, exec, kubeClient) + err := cni.CmdAdd(args, exec, kubeClient) os.Stdout = origStdout stdW.Close() var buf bytes.Buffer @@ -380,7 +371,7 @@ func TestCmdGet(t *testing.T) { var exec invoke.Exec args := testdata.GetTestArgs() kubeClient := fake.NewSimpleClientset() - assert.NoError(t, cmdGet(args, exec, kubeClient), "Unexpected error") + assert.NoError(t, cni.CmdGet(args, exec, kubeClient), "Unexpected error") }) } @@ -473,7 +464,7 @@ func TestCmdDel(t *testing.T) { defer cniovs.SetDefaultExecCommand() } - err := cmdDel(args, exec, kubeClient) + err := cni.CmdDel(args, exec, kubeClient) if tc.expError == "" { assert.NoError(t, err, "Unexpected error")