diff --git a/client/fingerprint/plugins_cni.go b/client/fingerprint/plugins_cni.go index e1eb89d3e..8100521c7 100644 --- a/client/fingerprint/plugins_cni.go +++ b/client/fingerprint/plugins_cni.go @@ -40,24 +40,28 @@ func (f *PluginsCNIFingerprint) Fingerprint(req *FingerprintRequest, resp *Finge return nil } - // list the cni_path directory - entries, err := f.lister(cniPath) - switch { - case err != nil: - f.logger.Warn("failed to read CNI plugins directory", "cni_path", cniPath, "error", err) - resp.Detected = false - return nil - case len(entries) == 0: - f.logger.Debug("no CNI plugins found", "cni_path", cniPath) - resp.Detected = true - return nil - } + // cniPath could be a multi-path, e.g. /opt/cni/bin:/custom/cni/bin + cniPathList := filepath.SplitList(cniPath) + for _, cniPath = range cniPathList { + // list the cni_path directory + entries, err := f.lister(cniPath) + switch { + case err != nil: + f.logger.Warn("failed to read CNI plugins directory", "cni_path", cniPath, "error", err) + resp.Detected = false + return nil + case len(entries) == 0: + f.logger.Debug("no CNI plugins found", "cni_path", cniPath) + resp.Detected = true + return nil + } - // for each file in cni_path, detect executables and try to get their version - for _, entry := range entries { - v, ok := f.detectOne(cniPath, entry) - if ok { - resp.AddAttribute(f.attribute(entry.Name()), v) + // for each file in cni_path, detect executables and try to get their version + for _, entry := range entries { + v, ok := f.detectOnePlugin(cniPath, entry) + if ok { + resp.AddAttribute(f.attribute(entry.Name()), v) + } } } @@ -70,7 +74,7 @@ func (f *PluginsCNIFingerprint) attribute(filename string) string { return fmt.Sprintf("%s.%s", cniPluginAttribute, filename) } -func (f *PluginsCNIFingerprint) detectOne(cniPath string, entry os.DirEntry) (string, bool) { +func (f *PluginsCNIFingerprint) detectOnePlugin(pluginPath string, entry os.DirEntry) (string, bool) { fi, err := entry.Info() if err != nil { f.logger.Debug("failed to read cni directory entry", "error", err) @@ -82,7 +86,7 @@ func (f *PluginsCNIFingerprint) detectOne(cniPath string, entry os.DirEntry) (st return "", false // not executable } - exePath := filepath.Join(cniPath, fi.Name()) + exePath := filepath.Join(pluginPath, fi.Name()) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() diff --git a/client/fingerprint/plugins_cni_test.go b/client/fingerprint/plugins_cni_test.go index 4a03baec0..95e1b0e23 100644 --- a/client/fingerprint/plugins_cni_test.go +++ b/client/fingerprint/plugins_cni_test.go @@ -30,6 +30,28 @@ func TestPluginsCNIFingerprint_Fingerprint_present(t *testing.T) { must.Eq(t, "v1.0.2", response.Attributes[attrBridge]) } +func TestPluginsCNIFingerprint_Fingerprint_multi(t *testing.T) { + ci.Parallel(t) + + f := NewPluginsCNIFingerprint(testlog.HCLogger(t)) + request := &FingerprintRequest{ + Config: &config.Config{ + CNIPath: "./test_fixtures/cni:./test_fixtures/cni2", + }, + } + response := new(FingerprintResponse) + + err := f.Fingerprint(request, response) + must.NoError(t, err) + must.True(t, response.Detected) + attrCustom := f.(*PluginsCNIFingerprint).attribute("custom") + attrBridge := f.(*PluginsCNIFingerprint).attribute("bridge") + attrCustom2 := f.(*PluginsCNIFingerprint).attribute("custom2") + must.Eq(t, "v1.2.3", response.Attributes[attrCustom]) + must.Eq(t, "v1.0.2", response.Attributes[attrBridge]) + must.Eq(t, "v9.9.9", response.Attributes[attrCustom2]) +} + func TestPluginsCNIFingerprint_Fingerprint_absent(t *testing.T) { ci.Parallel(t) diff --git a/client/fingerprint/test_fixtures/cni2/custom2 b/client/fingerprint/test_fixtures/cni2/custom2 new file mode 100755 index 000000000..5632e3a9c --- /dev/null +++ b/client/fingerprint/test_fixtures/cni2/custom2 @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Custom v9.9.9 Plugin"