From c7093b6c7b9b9442b6c39f7fcccca1f2f0acb506 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Thu, 30 Jan 2025 11:08:39 +0100 Subject: [PATCH] Update golangci-lint and config Signed-off-by: Sascha Grunert --- .golangci.yml | 9 +++- Makefile | 2 +- pkg/ocicni/ocicni.go | 88 ++++++++++++++++++++++++++++++++++ pkg/ocicni/ocicni_test.go | 18 ++++++- pkg/ocicni/util.go | 1 + pkg/ocicni/util_linux.go | 8 ++++ tools/ocicnitool/ocicnitool.go | 9 ++++ 7 files changed, 131 insertions(+), 4 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 84e52e0b..fca94cd8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,7 @@ linters: - errname - errorlint - exhaustive + - exptostd - fatcontext - forbidigo - forcetypeassert @@ -48,6 +49,7 @@ linters: - gosmopolitan - govet - grouper + - iface - importas - inamedparam - ineffassign @@ -62,7 +64,9 @@ linters: - nakedret - nestif - nilerr + - nilnesserr - nilnil + - nlreturn - noctx - nolintlint - nosprintfhostport @@ -73,6 +77,7 @@ linters: - promlinter - protogetter - reassign + - recvcheck - revive - rowserrcheck - sloglint @@ -91,8 +96,10 @@ linters: - unparam - unused - usestdlibvars + - usetesting - wastedassign - whitespace + - wsl - zerologlint # - cyclop # - depguard @@ -104,13 +111,11 @@ linters: # - ireturn # - lll # - mnd - # - nlreturn # - nonamedreturns # - tagliatelle # - testpackage # - varnamelen # - wrapcheck - # - wsl linters-settings: revive: rules: diff --git a/Makefile b/Makefile index 6d95f836..0284f7a4 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ BUILD_INFO := $(shell date +%s) BUILD_PATH := $(shell pwd)/build GOLANGCI_LINT := ${BUILD_PATH}/golangci-lint -GOLANGCI_LINT_VERSION := v1.61.0 +GOLANGCI_LINT_VERSION := v1.63.4 # If GOPATH not specified, use one in the local directory ifeq ($(GOPATH),) diff --git a/pkg/ocicni/ocicni.go b/pkg/ocicni/ocicni.go index d5aa0728..173b0bec 100644 --- a/pkg/ocicni/ocicni.go +++ b/pkg/ocicni/ocicni.go @@ -89,11 +89,13 @@ func (plugin *cniNetworkPlugin) podLock(podNetwork *PodNetwork) { plugin.podsLock.Lock() fullPodName := buildFullPodName(podNetwork) + lock, ok := plugin.pods[fullPodName] if !ok { lock = &podLock{} plugin.pods[fullPodName] = lock } + lock.refcount++ plugin.podsLock.Unlock() lock.mu.Lock() @@ -108,17 +110,22 @@ func (plugin *cniNetworkPlugin) podUnlock(podNetwork *PodNetwork) { fullPodName := buildFullPodName(podNetwork) lock, ok := plugin.pods[fullPodName] + if !ok { logrus.Errorf("Cannot find reference in refcount map for %s. Refcount cannot be determined.", fullPodName) + return } else if lock.refcount == 0 { // This should never ever happen, but handle it anyway delete(plugin.pods, fullPodName) logrus.Errorf("Pod lock for %s still in map with zero refcount", fullPodName) + return } + lock.refcount-- lock.mu.Unlock() + if lock.refcount == 0 { delete(plugin.pods, fullPodName) } @@ -136,6 +143,7 @@ func newWatcher(dirs []string) (*fsnotify.Watcher, error) { if err != nil { return nil, fmt.Errorf("failed to create new watcher %w", err) } + defer func() { // Close watcher on error if err != nil { @@ -155,8 +163,11 @@ func newWatcher(dirs []string) (*fsnotify.Watcher, error) { func (plugin *cniNetworkPlugin) monitorConfDir(ctx context.Context, start *sync.WaitGroup) { start.Done() plugin.done.Add(1) + defer plugin.done.Done() + exts := []string{".conf", ".conflist", ".json"} + for { select { case event := <-plugin.watcher.Events: @@ -165,9 +176,11 @@ func (plugin *cniNetworkPlugin) monitorConfDir(ctx context.Context, start *sync. } var defaultDeleted bool + createWriteRename := event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Rename == fsnotify.Rename + if event.Op&fsnotify.Remove == fsnotify.Remove { // Care about the event if the default network // was just deleted @@ -176,12 +189,14 @@ func (plugin *cniNetworkPlugin) monitorConfDir(ctx context.Context, start *sync. defaultDeleted = true } } + if !createWriteRename && !defaultDeleted { continue } if err := plugin.syncNetworkConfig(ctx); err != nil { logrus.Errorf("CNI config loading failed, continue monitoring: %v", err) + continue } @@ -189,7 +204,9 @@ func (plugin *cniNetworkPlugin) monitorConfDir(ctx context.Context, start *sync. if err == nil { continue } + logrus.Errorf("CNI monitoring error %v", err) + return case <-plugin.shutdownChan: @@ -226,6 +243,7 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName, confDir string, useI if confDir == "" { confDir = DefaultConfDir } + if len(binDirs) == 0 { binDirs = []string{DefaultBinDir} } @@ -259,6 +277,7 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName, confDir string, useI if err != nil { return nil, err } + plugin.nsManager = nsm ctx := context.Background() @@ -274,6 +293,7 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName, confDir string, useI startWg := sync.WaitGroup{} startWg.Add(1) + go plugin.monitorConfDir(ctx, &startWg) startWg.Wait() } @@ -283,10 +303,13 @@ func initCNI(exec cniinvoke.Exec, cacheDir, defaultNetName, confDir string, useI func (plugin *cniNetworkPlugin) Shutdown() error { close(plugin.shutdownChan) + if plugin.watcher != nil { plugin.watcher.Close() } + plugin.done.Wait() + return nil } @@ -299,6 +322,7 @@ func loadNetworks(ctx context.Context, confDir string, cni *libcni.CNIConfig) (n networks = make(map[string]*cniNetwork) sort.Strings(files) + for _, confFile := range files { var confList *libcni.NetworkConfigList if strings.HasSuffix(confFile, ".conflist") { @@ -308,6 +332,7 @@ func loadNetworks(ctx context.Context, confDir string, cni *libcni.CNIConfig) (n if !os.IsNotExist(err) { logrus.Errorf("Error loading CNI config list file %s: %v", confFile, err) } + continue } } else { @@ -317,20 +342,27 @@ func loadNetworks(ctx context.Context, confDir string, cni *libcni.CNIConfig) (n if !os.IsNotExist(err) { logrus.Errorf("Error loading CNI config file %s: %v", confFile, err) } + continue } + if conf.Network.Type == "" { logrus.Warningf("Error loading CNI config file %s: no 'type'; perhaps this is a .conflist?", confFile) + continue } + confList, err = libcni.ConfListFromConf(conf) if err != nil { logrus.Errorf("Error converting CNI config file %s to list: %v", confFile, err) + continue } } + if len(confList.Plugins) == 0 { logrus.Infof("CNI config list %s has no networks, skipping", confFile) + continue } @@ -338,6 +370,7 @@ func loadNetworks(ctx context.Context, confDir string, cni *libcni.CNIConfig) (n // of plugins which are necessary. if _, err := cni.ValidateNetworkList(ctx, confList); err != nil { logrus.Warningf("Error validating CNI config file %s: %v", confFile, err) + continue } @@ -383,6 +416,7 @@ func (plugin *cniNetworkPlugin) syncNetworkConfig(ctx context.Context) error { // Update defaultNetName if it is changeable if plugin.defaultNetName.changeable { plugin.defaultNetName.name = defaultNetName + if defaultNetName != "" { logrus.Infof("Updated default CNI network name to %s", defaultNetName) } @@ -398,6 +432,7 @@ func (plugin *cniNetworkPlugin) syncNetworkConfig(ctx context.Context) error { func (plugin *cniNetworkPlugin) GetDefaultNetworkName() string { plugin.RLock() defer plugin.RUnlock() + return plugin.defaultNetName.name } @@ -409,10 +444,12 @@ func (plugin *cniNetworkPlugin) getDefaultNetwork() *cniNetwork { if defaultNetName == "" { return nil } + network, ok := plugin.networks[defaultNetName] if !ok { logrus.Debugf("Failed to get network for name: %s", defaultNetName) } + return network } @@ -423,6 +460,7 @@ func (plugin *cniNetworkPlugin) networksAvailable(podNetwork *PodNetwork) error if len(podNetwork.Networks) == 0 && plugin.getDefaultNetwork() == nil { return fmt.Errorf(errMissingDefaultNetwork, plugin.confDir) } + return nil } @@ -439,7 +477,9 @@ func (plugin *cniNetworkPlugin) loadNetworkFromCache(name string, rt *libcni.Run } var confBytes []byte + var err error + confBytes, rt, err = plugin.cniConfig.GetNetworkListCachedConfig(cniNet.config, rt) if err != nil { return nil, nil, err @@ -477,12 +517,14 @@ func (plugin *cniNetworkPlugin) fillPodNetworks(podNetwork *PodNetwork) error { } allIfNames := make(map[string]bool) + for _, net := range podNetwork.Networks { if net.Ifname != "" { // Make sure the requested name isn't already assigned if allIfNames[net.Ifname] { return fmt.Errorf("network %q requested interface name %q already assigned", net.Name, net.Ifname) } + allIfNames[net.Ifname] = true } } @@ -494,12 +536,15 @@ netLoop: if !allIfNames[candidate] { allIfNames[candidate] = true podNetwork.Networks[i].Ifname = candidate + continue netLoop } } + return fmt.Errorf("failed to find free interface name for network %q", network.Name) } } + return nil } @@ -511,6 +556,7 @@ func (plugin *cniNetworkPlugin) forEachNetwork(ctx context.Context, podNetwork * if err := plugin.fillPodNetworks(podNetwork); err != nil { logrus.Errorf("Error filling interface names: %v", err) + return err } @@ -518,9 +564,11 @@ func (plugin *cniNetworkPlugin) forEachNetwork(ctx context.Context, podNetwork * // See if we need to re-sync the configuration, which can happen // in some racy podman tests. See PR #85. missingNetworks := false + for _, net := range podNetwork.Networks { if _, ok := plugin.networks[net.Name]; !ok { missingNetworks = true + break } } @@ -537,15 +585,19 @@ func (plugin *cniNetworkPlugin) forEachNetwork(ctx context.Context, podNetwork * for _, network := range podNetwork.Networks { runtimeConfig := podNetwork.RuntimeConfig[network.Name] + rt, err := buildCNIRuntimeConf(podNetwork, network.Ifname, &runtimeConfig) if err != nil { logrus.Errorf("Error building CNI runtime config: %v", err) + return err } var cniNet *cniNetwork + if fromCache { var newRt *libcni.RuntimeConf + cniNet, newRt, err = plugin.loadNetworkFromCache(network.Name, rt) if err != nil { logrus.Errorf("Error loading cached network config: %v", err) @@ -555,6 +607,7 @@ func (plugin *cniNetworkPlugin) forEachNetwork(ctx context.Context, podNetwork * rt = newRt } } + if cniNet == nil { cniNet = plugin.networks[network.Name] if cniNet == nil { @@ -566,6 +619,7 @@ func (plugin *cniNetworkPlugin) forEachNetwork(ctx context.Context, podNetwork * return err } } + return nil } @@ -589,10 +643,12 @@ func (plugin *cniNetworkPlugin) SetUpPodWithContext(ctx context.Context, podNetw // Set up loopback interface if err := bringUpLoopback(podNetwork.NetNS); err != nil { logrus.Error(err) + return nil, err } results := make([]NetResult, 0) + if err := plugin.forEachNetwork(ctx, &podNetwork, false, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { fullPodName := buildFullPodName(podNetwork) logrus.Infof("Adding pod %s to CNI network %q (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) @@ -607,6 +663,7 @@ func (plugin *cniNetworkPlugin) SetUpPodWithContext(ctx context.Context, podNetw Ifname: rt.IfName, }, }) + return nil }); err != nil { return nil, err @@ -622,6 +679,7 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA } dirPath := filepath.Join(cacheDir, "results") + entries, err := os.ReadDir(dirPath) if err != nil { return nil, err @@ -631,20 +689,25 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA for _, e := range entries { fileNames = append(fileNames, e.Name()) } + sort.Strings(fileNames) attachments := []NetAttachment{} + for _, fname := range fileNames { part := fmt.Sprintf("-%s-", containerID) pos := strings.Index(fname, part) + if pos <= 0 || pos+len(part) >= len(fname) { continue } cacheFile := filepath.Join(dirPath, fname) + bytes, err := os.ReadFile(cacheFile) if err != nil { logrus.Errorf("Failed to read CNI cache file %s: %v", cacheFile, err) + continue } @@ -657,12 +720,16 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA if err := json.Unmarshal(bytes, &cachedInfo); err != nil { logrus.Errorf("Failed to unmarshal CNI cache file %s: %v", cacheFile, err) + continue } + if cachedInfo.Kind != libcni.CNICacheV1 { logrus.Warningf("Unknown CNI cache file %s kind %q", cacheFile, cachedInfo.Kind) + continue } + if cachedInfo.ContainerID != containerID { continue } @@ -670,8 +737,10 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA if cachedInfo.IfName == loIfname && cachedInfo.NetName == "cni-loopback" { continue } + if cachedInfo.IfName == "" || cachedInfo.NetName == "" { logrus.Warningf("Missing CNI cache file %s ifname %q or netname %q", cacheFile, cachedInfo.IfName, cachedInfo.NetName) + continue } @@ -680,6 +749,7 @@ func (plugin *cniNetworkPlugin) getCachedNetworkInfo(containerID string) ([]NetA Ifname: cachedInfo.IfName, }) } + return attachments, nil } @@ -703,6 +773,7 @@ func (plugin *cniNetworkPlugin) TearDownPodWithContext(ctx context.Context, podN if err := plugin.networksAvailable(&podNetwork); err != nil { return err } + plugin.gcLock.RLock() defer plugin.gcLock.RUnlock() @@ -712,9 +783,11 @@ func (plugin *cniNetworkPlugin) TearDownPodWithContext(ctx context.Context, podN return plugin.forEachNetwork(ctx, &podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { fullPodName := buildFullPodName(podNetwork) logrus.Infof("Deleting pod %s from CNI network %q (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) + if err := network.deleteFromNetwork(ctx, rt, plugin.cniConfig); err != nil { return fmt.Errorf("error removing pod %s from CNI network %q: %w", fullPodName, network.name, err) } + return nil }) } @@ -737,10 +810,12 @@ func (plugin *cniNetworkPlugin) GetPodNetworkStatusWithContext(ctx context.Conte if err := checkLoopback(podNetwork.NetNS); err != nil { logrus.Error(err) + return nil, err } results := make([]NetResult, 0) + if err := plugin.forEachNetwork(ctx, &podNetwork, true, func(network *cniNetwork, podNetwork *PodNetwork, rt *libcni.RuntimeConf) error { fullPodName := buildFullPodName(podNetwork) logrus.Infof("Checking pod %s for CNI network %s (type=%v)", fullPodName, network.name, network.config.Plugins[0].Network.Type) @@ -757,6 +832,7 @@ func (plugin *cniNetworkPlugin) GetPodNetworkStatusWithContext(ctx context.Conte }, }) } + return nil }); err != nil { return nil, err @@ -780,6 +856,7 @@ func (plugin *cniNetworkPlugin) GC(ctx context.Context, validPods []*PodNetwork) // for every network, determine the set of valid attachments -- (ID, ifname) pairs validAttachments := map[string][]cnitypes.GCAttachment{} + for _, pod := range validPods { _ = plugin.fillPodNetworks(pod) // cannot have error here; or else pod could not have been ADDed @@ -798,6 +875,7 @@ func (plugin *cniNetworkPlugin) GC(ctx context.Context, validPods []*PodNetwork) args := &libcni.GCArgs{ ValidAttachments: validAttachments[netname], } + err := network.gcNetwork(ctx, plugin.cniConfig, args) if err != nil { logrus.Warnf("Error while GCing network %s: %v", netname, err) @@ -824,8 +902,10 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC if gtet { err = cni.CheckNetworkList(ctx, network.config, rt) logrus.Infof("Checking CNI network %s (config version=%v)", network.name, network.config.CNIVersion) + if err != nil { logrus.Errorf("Error checking network: %v", err) + return nil, err } } @@ -833,6 +913,7 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC result, err = cni.GetNetworkListCachedResult(network.config, rt) if err != nil { logrus.Errorf("Error getting network list cached result: %v", err) + return nil, err } else if result != nil { return result, nil @@ -842,8 +923,10 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC logrus.Infof("Checking CNI network %s (config version=%v) nsManager=%v", network.name, network.config.CNIVersion, nsManager) var cniInterface *cniv1.Interface + ips := []*cniv1.IPConfig{} errs := []error{} + for _, version := range []string{"4", "6"} { ip, mac, err := getContainerDetails(nsManager, netns, rt.IfName, "-"+version) if err == nil { @@ -854,6 +937,7 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC Sandbox: netns, } } + ips = append(ips, &cniv1.IPConfig{ Interface: cniv1.Int(0), Address: *ip, @@ -862,6 +946,7 @@ func (network *cniNetwork) checkNetwork(ctx context.Context, rt *libcni.RuntimeC errs = append(errs, err) } } + if cniInterface == nil || len(ips) == 0 { return nil, fmt.Errorf("neither IPv4 nor IPv6 found when retrieving network status: %v", errs) } @@ -897,6 +982,7 @@ func buildCNIRuntimeConf(podNetwork *PodNetwork, ifName string, runtimeConfig *R if runtimeConfig == nil { runtimeConfig = &RuntimeConfig{} } + logrus.Infof("Got pod network %+v", podNetwork) rt := &libcni.RuntimeConf{ @@ -926,6 +1012,7 @@ func buildCNIRuntimeConf(podNetwork *PodNetwork, ifName string, runtimeConfig *R if tstIP := net.ParseIP(ip); tstIP == nil { return nil, fmt.Errorf("unable to parse IP address %q", ip) } + rt.Args = append(rt.Args, [2]string{"IP", ip}) } @@ -936,6 +1023,7 @@ func buildCNIRuntimeConf(podNetwork *PodNetwork, ifName string, runtimeConfig *R if err != nil { return nil, fmt.Errorf("unable to parse MAC address %q: %w", mac, err) } + rt.Args = append(rt.Args, [2]string{"MAC", mac}) } diff --git a/pkg/ocicni/ocicni_test.go b/pkg/ocicni/ocicni_test.go index e1e491e3..59368e7c 100644 --- a/pkg/ocicni/ocicni_test.go +++ b/pkg/ocicni/ocicni_test.go @@ -30,6 +30,7 @@ func writeConfig(dir, fileName, netName, plugin, vers string) (conf, confPath st "type": "%s", "cniVersion": "%s" }`, netName, plugin, vers) + return conf, confPath, os.WriteFile(confPath, []byte(conf), 0o644) } @@ -94,11 +95,14 @@ func (f *fakeExec) addPlugin(expectedEnv []string, expectedConf string, result t // Ensure everything in needles is also present in haystack. func matchArray(needles, haystack []string) { Expect(len(needles)).To(BeNumerically("<=", len(haystack))) + for _, e1 := range needles { found := "" + for _, e2 := range haystack { if e1 == e2 { found = e2 + break } } @@ -114,13 +118,16 @@ func getCNICommand(env []string) (string, error) { return parts[1], nil } } + return "", errors.New("failed to find CNI_COMMAND") } func (f *fakeExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) { cmd, err := getCNICommand(environ) Expect(err).NotTo(HaveOccurred()) + var index int + switch cmd { case "ADD": Expect(len(f.plugins)).To(BeNumerically(">", f.addIndex)) @@ -131,7 +138,7 @@ func (f *fakeExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData index = f.delIndex f.delIndex++ case "CHECK": - Expect(len(f.plugins)).To(BeNumerically("==", f.addIndex)) + Expect(f.plugins).To(HaveLen(f.addIndex)) index = f.chkIndex f.chkIndex++ case "GC": @@ -145,11 +152,13 @@ func (f *fakeExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData if f.failStatus { return nil, errors.New("status fails") } + return nil, nil default: // Should never be reached Expect(false).To(BeTrue()) } + plugin := f.plugins[index] GinkgoT().Logf("[%s %d] exec plugin %q found %+v", cmd, index, pluginPath, plugin) @@ -161,6 +170,7 @@ func (f *fakeExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData testData, err := json.Marshal(testConf) Expect(err).NotTo(HaveOccurred()) + if plugin.expectedConf != "" { Expect(string(testData)).To(MatchJSON(plugin.expectedConf)) } @@ -178,6 +188,7 @@ func (f *fakeExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData resultJSON, err = json.Marshal(plugin.result) Expect(err).NotTo(HaveOccurred()) } + return resultJSON, nil } @@ -187,13 +198,16 @@ func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) { if f.failFind { return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) } + return filepath.Join(paths[0], plugin), nil } func ensureCIDR(cidr string) *net.IPNet { ip, network, err := net.ParseCIDR(cidr) Expect(err).NotTo(HaveOccurred()) + network.IP = ip + return network } @@ -306,6 +320,7 @@ var _ = Describe("ocicni operations", func() { if net.config.Plugins[0].Network.Type != "myplugin" { return errors.New("wrong plugin type") } + return nil }, 10).Should(Succeed()) @@ -668,6 +683,7 @@ var _ = Describe("ocicni operations", func() { link, err := netlink.LinkByName("lo") Expect(err).NotTo(HaveOccurred()) Expect(link.Attrs().Flags & net.FlagUp).To(Equal(net.FlagUp)) + return nil }) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/ocicni/util.go b/pkg/ocicni/util.go index 2af78659..b8f6b4fa 100644 --- a/pkg/ocicni/util.go +++ b/pkg/ocicni/util.go @@ -4,5 +4,6 @@ package ocicni func newNSManager() (*nsManager, error) { nsm := &nsManager{} err := nsm.init() + return nsm, err } diff --git a/pkg/ocicni/util_linux.go b/pkg/ocicni/util_linux.go index 9c73bab5..96d90ee8 100644 --- a/pkg/ocicni/util_linux.go +++ b/pkg/ocicni/util_linux.go @@ -23,6 +23,7 @@ type nsManager struct { func (nsm *nsManager) init() error { var err error nsm.nsenterPath, err = exec.LookPath(defaultNamespaceEnterCommandName) + return err } @@ -38,14 +39,17 @@ func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType stri if len(lines) < 1 { return nil, nil, fmt.Errorf("unexpected command output %s", output) } + fields := strings.Fields(lines[0]) if len(fields) < 4 { return nil, nil, fmt.Errorf("unexpected address output %s ", lines[0]) } + ip, ipNet, err := net.ParseCIDR(fields[3]) if err != nil { return nil, nil, fmt.Errorf("CNI failed to parse ip from output %s due to %w", output, err) } + if ip.To4() == nil { ipNet.IP = ip } else { @@ -63,10 +67,12 @@ func getContainerDetails(nsm *nsManager, netnsPath, interfaceName, addrType stri if len(lines) < 2 { return nil, nil, fmt.Errorf("unexpected 'ip link' command output %s", output) } + fields = strings.Fields(lines[1]) if len(fields) < 4 { return nil, nil, fmt.Errorf("unexpected link output %s ", lines[0]) } + mac, err := net.ParseMAC(fields[1]) if err != nil { return nil, nil, fmt.Errorf("failed to parse MAC from output %s due to %w", output, err) @@ -115,6 +121,7 @@ func bringUpLoopback(netns string) error { }); err != nil { return fmt.Errorf("error adding loopback interface: %w", err) } + return nil } @@ -134,5 +141,6 @@ func checkLoopback(netns string) error { }); err != nil { return fmt.Errorf("error checking loopback interface: %w", err) } + return nil } diff --git a/tools/ocicnitool/ocicnitool.go b/tools/ocicnitool/ocicnitool.go index d6327deb..5ff5953d 100644 --- a/tools/ocicnitool/ocicnitool.go +++ b/tools/ocicnitool/ocicnitool.go @@ -26,6 +26,7 @@ func printSandboxResults(results []ocicni.NetResult) { if err == nil { for _, ip := range result.IPs { intfDetails := "" + if ip.Interface != nil && *ip.Interface >= 0 && *ip.Interface < len(result.Interfaces) { intf := result.Interfaces[*ip.Interface] // Only print container sandbox interfaces (not host ones) @@ -33,6 +34,7 @@ func printSandboxResults(results []ocicni.NetResult) { intfDetails = fmt.Sprintf(" (%s %s)", intf.Name, intf.Mac) } } + fmt.Fprintf(os.Stdout, "IP: %s%s\n", ip.Address.String(), intfDetails) } } @@ -42,7 +44,9 @@ func printSandboxResults(results []ocicni.NetResult) { func main() { networksStr := flag.String("networks", "", "comma-separated list of CNI network names (optional)") flag.Parse() + networks := make([]string, 0) + for _, name := range strings.Split(*networksStr, ",") { if name != "" { networks = append(networks, name) @@ -60,6 +64,7 @@ func main() { if len(flag.Args()) < 5 { flag.Usage() + return } @@ -67,6 +72,7 @@ func main() { if confdir == "" { confdir = ocicni.DefaultConfDir } + bindir := os.Getenv(EnvBinDir) if bindir == "" { bindir = ocicni.DefaultBinDir @@ -96,12 +102,14 @@ func main() { if err == nil { printSandboxResults(results) } + exit(err) case CmdStatus: results, err := plugin.GetPodNetworkStatus(podNetwork) if err == nil { printSandboxResults(results) } + exit(err) case CmdDel: exit(plugin.TearDownPod(podNetwork)) @@ -113,5 +121,6 @@ func exit(err error) { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } + os.Exit(0) }