func RunCNIPluginWithId(
	netconf,
	podName,
	podNamespace,
	ip,
	containerId,
	ifName string,
	targetNs ns.NetNS,
) (
	result *current.Result,
	contVeth netlink.Link,
	contAddr []netlink.Addr,
	contRoutes []netlink.Route,
	err error,
) {
	k8sEnv := ""
	if podName != "" {
		k8sEnv = fmt.Sprintf("CNI_ARGS=K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_INFRA_CONTAINER_ID=whatever", podName, podNamespace)
		if ip != "" {
			k8sEnv = fmt.Sprintf("%s;IP=%s", k8sEnv, ip)
		}
	}
	if ifName == "" {
		ifName = "eth0"
	}
	env := []string{
		"CNI_COMMAND=ADD",
		fmt.Sprintf("CNI_IFNAME=%s", ifName),
		fmt.Sprintf("CNI_PATH=%s", os.Getenv("BIN")),
		fmt.Sprintf("CNI_CONTAINERID=%s", containerId),
		fmt.Sprintf("CNI_NETNS=%s", targetNs.Path()),
		k8sEnv,
	}
	args := &cniArgs{env}
	log.Debugf("Calling CNI plugin with the following env vars: %v", env)
	var r types.Result
	pluginPath := fmt.Sprintf("%s/%s", os.Getenv("BIN"), os.Getenv("PLUGIN"))
	r, err = invoke.ExecPluginWithResult(context.Background(), pluginPath, []byte(netconf), args, nil)
	if err != nil {
		return
	}
	var nc types.NetConf
	if err = json.Unmarshal([]byte(netconf), &nc); err != nil {
		panic(err)
	}
	if version.Compare(nc.CNIVersion, "0.3.0", "<") {
		var out []byte
		out, err = json.Marshal(r)
		log.Infof("CNI output: %s", out)
		r020 := types020.Result{}
		if err = json.Unmarshal(out, &r020); err != nil {
			log.Errorf("Error unmarshaling output to Result: %v\n", err)
			return
		}
		result, err = current.NewResultFromResult(&r020)
		if err != nil {
			return
		}
	} else {
		result, err = current.GetResult(r)
		if err != nil {
			return
		}
	}
	err = targetNs.Do(func(_ ns.NetNS) error {
		contVeth, err = netlink.LinkByName(ifName)
		if err != nil {
			return err
		}
		contAddr, err = netlink.AddrList(contVeth, syscall.AF_INET)
		if err != nil {
			return err
		}
		v6Addrs, err := netlink.AddrList(contVeth, syscall.AF_INET6)
		if err != nil {
			return err
		}
		for _, addr := range v6Addrs {
			if !strings.HasPrefix(addr.IPNet.String(), "fe80:") {
				contAddr = append(contAddr, addr)
			}
		}
		contRoutes, err = netlink.RouteList(contVeth, syscall.AF_INET)
		if err != nil {
			return err
		}
		return nil
	})
	return
}
RunCNIPluginWithId calls CNI plugin with a containerID and targetNs passed to it.
This is for when you want to call CNI for an existing container.
package testutils
import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"github.com/containernetworking/cni/pkg/invoke"
	"github.com/containernetworking/cni/pkg/types"
	types020 "github.com/containernetworking/cni/pkg/types/020"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/containernetworking/plugins/pkg/ns"
	"github.com/containernetworking/plugins/pkg/testutils"
	"github.com/mcuadros/go-version"
	"github.com/onsi/ginkgo"
	"github.com/onsi/gomega/gexec"
	k8sconversion "github.com/projectcalico/libcalico-go/lib/backend/k8s/conversion"
	"github.com/projectcalico/libcalico-go/lib/names"
	log "github.com/sirupsen/logrus"
	"github.com/vishvananda/netlink"
)
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func GetResultForCurrent(session *gexec.Session, cniVersion string) (*current.Result, error) {
	if version.Compare(cniVersion, "0.3.0", "<") {
		r020 := types020.Result{}
		if err := json.Unmarshal(session.Out.Contents(), &r020); err != nil {
			log.Errorf("Error unmarshaling output to Result: %v\n", err)
			return nil, err
		}
		rCurrent, err := current.NewResultFromResult(&r020)
		if err != nil {
			return nil, err
		}
		return rCurrent, nil
	}
	r := current.Result{}
	if err := json.Unmarshal(session.Out.Contents(), &r); err != nil {
		log.Errorf("Error unmarshaling output to Result: %v\n", err)
		return nil, err
	}
	return &r, nil
}
func RunIPAMPlugin(netconf, command, args, cid, cniVersion string) (*current.Result, types.Error, int) {
	conf := types.NetConf{}
	if err := json.Unmarshal([]byte(netconf), &conf); err != nil {
		panic(fmt.Errorf("failed to load netconf: %v", err))
	}
	cmd := &exec.Cmd{
		Env: []string{
			fmt.Sprintf("CNI_CONTAINERID=%s", cid),
			"CNI_NETNS=b",
			"CNI_IFNAME=c",
			"CNI_PATH=d",
			fmt.Sprintf("CNI_COMMAND=%s", command),
			fmt.Sprintf("CNI_ARGS=%s", args),
		},
		Path: fmt.Sprintf("%s/%s", os.Getenv("BIN"), conf.IPAM.Type),
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		panic("some error found")
	}
	_, err = io.WriteString(stdin, netconf)
	if err != nil {
		panic(err)
	}
	_, err = io.WriteString(stdin, "\n")
	if err != nil {
		panic(err)
	}
	err = stdin.Close()
	if err != nil {
		panic(err)
	}
	session, err := gexec.Start(cmd, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
	if err != nil {
		panic("some error found")
	}
	session.Wait(5)
	exitCode := session.ExitCode()
	result := &current.Result{}
	e := types.Error{}
	stdout := session.Out.Contents()
	if exitCode == 0 {
		if command == "ADD" {
			result, err = GetResultForCurrent(session, cniVersion)
			if err != nil {
				log.Errorf("Error getting result from the session: %v \n %v\n", session, err)
				panic(err)
			}
		}
	} else {
		if err := json.Unmarshal(stdout, &e); err != nil {
			panic(fmt.Errorf("failed to load error: %s %v", stdout, err))
		}
	}
	return result, e, exitCode
}
func CreateContainerNamespace() (containerNs ns.NetNS, containerId string, err error) {
	containerNs, err = testutils.NewNS()
	if err != nil {
		return nil, "", err
	}
	netnsname := path.Base(containerNs.Path())
	containerId = netnsname[:10]
	err = containerNs.Do(func(_ ns.NetNS) error {
		lo, err := netlink.LinkByName("lo")
		if err != nil {
			return err
		}
		return netlink.LinkSetUp(lo)
	})
	return
}
func CreateContainer(netconf, podName, podNamespace, ip string) (containerID string, result *current.Result, contVeth netlink.Link, contAddr []netlink.Addr, contRoutes []netlink.Route, targetNs ns.NetNS, err error) {
	targetNs, containerID, err = CreateContainerNamespace()
	if err != nil {
		return "", nil, nil, nil, nil, nil, err
	}
	result, contVeth, contAddr, contRoutes, err = RunCNIPluginWithId(netconf, podName, podNamespace, ip, containerID, "", targetNs)
	return
}
func CreateContainerWithId(netconf, podName, podNamespace, ip, overrideContainerID string) (containerID string, result *current.Result, contVeth netlink.Link, contAddr []netlink.Addr, contRoutes []netlink.Route, targetNs ns.NetNS, err error) {
	targetNs, containerID, err = CreateContainerNamespace()
	if err != nil {
		return "", nil, nil, nil, nil, nil, err
	}
	if overrideContainerID != "" {
		containerID = overrideContainerID
	}
	result, contVeth, contAddr, contRoutes, err = RunCNIPluginWithId(netconf, podName, podNamespace, ip, containerID, "", targetNs)
	return
}