diff --git a/Documentation/cnitool.md b/Documentation/cnitool.md new file mode 100644 index 00000000..a4bc7d35 --- /dev/null +++ b/Documentation/cnitool.md @@ -0,0 +1,16 @@ +# Overview +The `cnitool` is a utility that can be used to test a CNI plugin +without the need for a container runtime. The `cnitool` takes a +`network name` and a `network namespace` and a command to `ADD` or +`DEL`,.i.e, attach or detach containers from a network. The `cnitool` +relies on the following environment variables to operate properly: +* `NETCONFPATH`: This environment variable needs to be set to a + directory. It defaults to `/etc/cni/net.d`. The `cnitool` searches + for CNI configuration files in this directory with the extension + `*.conf` or `*.json`. It loads all the CNI configuration files in + this directory and if it finds a CNI configuration with the `network + name` given to the cnitool it returns the corresponding CNI + configuration, else it returns `nil`. + +* `CNI_PATH`: For a given CNI configuration `cnitool` will search for + the corresponding CNI plugin in this path. diff --git a/libcni/conf.go b/libcni/conf.go index 4fa2bfed..c7738c66 100644 --- a/libcni/conf.go +++ b/libcni/conf.go @@ -16,7 +16,6 @@ package libcni import ( "encoding/json" - "errors" "fmt" "io/ioutil" "os" @@ -33,7 +32,13 @@ func (e NotFoundError) Error() string { return fmt.Sprintf(`no net configuration with name "%s" in %s`, e.Name, e.Dir) } -var NoConfigsFoundError = errors.New("no net configurations found") +type NoConfigsFoundError struct { + Dir string +} + +func (e NoConfigsFoundError) Error() string { + return fmt.Sprintf(`no net configurations found in %s`, e.Dir) +} func ConfFromBytes(bytes []byte) (*NetworkConfig, error) { conf := &NetworkConfig{Bytes: bytes} @@ -149,7 +154,7 @@ func LoadConf(dir, name string) (*NetworkConfig, error) { case err != nil: return nil, err case len(files) == 0: - return nil, NoConfigsFoundError + return nil, NoConfigsFoundError{Dir: dir} } sort.Strings(files) @@ -187,16 +192,12 @@ func LoadConfList(dir, name string) (*NetworkConfigList, error) { singleConf, err := LoadConf(dir, name) if err != nil { // A little extra logic so the error makes sense - switch { - // neither configlists nor config files found - case len(files) == 0 && err == NoConfigsFoundError: - return nil, err - // config lists found but no config files found - case len(files) != 0 && err == NoConfigsFoundError: + if _, ok := err.(NoConfigsFoundError); len(files) != 0 && ok { + // Config lists found but no config files found return nil, NotFoundError{dir, name} - default: // either not found or parse error - return nil, err } + + return nil, err } return ConfListFromConf(singleConf) } diff --git a/libcni/conf_test.go b/libcni/conf_test.go index 7ad525bb..225828e4 100644 --- a/libcni/conf_test.go +++ b/libcni/conf_test.go @@ -61,7 +61,7 @@ var _ = Describe("Loading configuration from disk", func() { It("returns a useful error", func() { _, err := libcni.LoadConf(configDir, "some-plugin") - Expect(err).To(MatchError("no net configurations found")) + Expect(err).To(MatchError(libcni.NoConfigsFoundError{Dir: configDir})) }) }) @@ -244,7 +244,7 @@ var _ = Describe("Loading configuration from disk", func() { It("returns a useful error", func() { _, err := libcni.LoadConfList(configDir, "some-plugin") - Expect(err).To(MatchError("no net configurations found")) + Expect(err).To(MatchError(libcni.NoConfigsFoundError{Dir: configDir})) }) })