libcni: up-convert a Config to a ConfigList when no other configs are found.
This commit is contained in:
parent
6f3b0abcc7
commit
6e6ad53ea8
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015 CoreOS, Inc.
|
// Copyright 2015 CNI authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@ -42,7 +42,7 @@ func main() {
|
|||||||
if netdir == "" {
|
if netdir == "" {
|
||||||
netdir = DefaultNetDir
|
netdir = DefaultNetDir
|
||||||
}
|
}
|
||||||
netconf, err := libcni.LoadConf(netdir, os.Args[2])
|
netconf, err := libcni.LoadConfList(netdir, os.Args[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
@ -61,10 +61,13 @@ func main() {
|
|||||||
|
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case CmdAdd:
|
case CmdAdd:
|
||||||
_, err := cninet.AddNetwork(netconf, rt)
|
result, err := cninet.AddNetworkList(netconf, rt)
|
||||||
|
if result != nil {
|
||||||
|
_ = result.Print()
|
||||||
|
}
|
||||||
exit(err)
|
exit(err)
|
||||||
case CmdDel:
|
case CmdDel:
|
||||||
exit(cninet.DelNetwork(netconf, rt))
|
exit(cninet.DelNetworkList(netconf, rt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ package libcni
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -23,6 +24,17 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type NotFoundError struct {
|
||||||
|
Dir string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
||||||
conf := &NetworkConfig{Bytes: bytes}
|
conf := &NetworkConfig{Bytes: bytes}
|
||||||
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
||||||
@ -137,7 +149,7 @@ func LoadConf(dir, name string) (*NetworkConfig, error) {
|
|||||||
case err != nil:
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
case len(files) == 0:
|
case len(files) == 0:
|
||||||
return nil, fmt.Errorf("no net configurations found")
|
return nil, NoConfigsFoundError
|
||||||
}
|
}
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
|
|
||||||
@ -150,16 +162,13 @@ func LoadConf(dir, name string) (*NetworkConfig, error) {
|
|||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf(`no net configuration with name "%s" in %s`, name, dir)
|
return nil, NotFoundError{dir, name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfList(dir, name string) (*NetworkConfigList, error) {
|
func LoadConfList(dir, name string) (*NetworkConfigList, error) {
|
||||||
files, err := ConfFiles(dir, []string{".conflist"})
|
files, err := ConfFiles(dir, []string{".conflist"})
|
||||||
switch {
|
if err != nil {
|
||||||
case err != nil:
|
|
||||||
return nil, err
|
return nil, err
|
||||||
case len(files) == 0:
|
|
||||||
return nil, fmt.Errorf("no net configuration lists found")
|
|
||||||
}
|
}
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
|
|
||||||
@ -172,7 +181,24 @@ func LoadConfList(dir, name string) (*NetworkConfigList, error) {
|
|||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf(`no net configuration list with name "%s" in %s`, name, dir)
|
|
||||||
|
// Try and load a network configuration file (instead of list)
|
||||||
|
// from the same name, then upconvert.
|
||||||
|
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:
|
||||||
|
return nil, NotFoundError{dir, name}
|
||||||
|
default: // either not found or parse error
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ConfListFromConf(singleConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*NetworkConfig, error) {
|
func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*NetworkConfig, error) {
|
||||||
@ -199,3 +225,29 @@ func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*Net
|
|||||||
|
|
||||||
return ConfFromBytes(newBytes)
|
return ConfFromBytes(newBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfListFromConf "upconverts" a network config in to a NetworkConfigList,
|
||||||
|
// with the single network as the only entry in the list.
|
||||||
|
func ConfListFromConf(original *NetworkConfig) (*NetworkConfigList, error) {
|
||||||
|
// Re-deserialize the config's json, then make a raw map configlist.
|
||||||
|
// This may seem a bit strange, but it's to make the Bytes fields
|
||||||
|
// actually make sense. Otherwise, the generated json is littered with
|
||||||
|
// golang default values.
|
||||||
|
|
||||||
|
rawConfig := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal(original.Bytes, &rawConfig); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawConfigList := map[string]interface{}{
|
||||||
|
"name": original.Network.Name,
|
||||||
|
"cniVersion": original.Network.CNIVersion,
|
||||||
|
"plugins": []interface{}{rawConfig},
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(rawConfigList)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ConfListFromBytes(b)
|
||||||
|
}
|
||||||
|
@ -184,6 +184,32 @@ var _ = Describe("Loading configuration from disk", func() {
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("when there is a config file with the same name as the list", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
configFile := []byte(`{
|
||||||
|
"name": "some-list",
|
||||||
|
"cniVersion": "0.2.0",
|
||||||
|
"type": "bridge"
|
||||||
|
}`)
|
||||||
|
Expect(ioutil.WriteFile(filepath.Join(configDir, "49-whatever.conf"), configFile, 0600)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("Loads the config list first", func() {
|
||||||
|
netConfigList, err := libcni.LoadConfList(configDir, "some-list")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(netConfigList.Plugins)).To(Equal(3))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("falls back to the config file", func() {
|
||||||
|
Expect(os.Remove(filepath.Join(configDir, "50-whatever.conflist"))).To(Succeed())
|
||||||
|
|
||||||
|
netConfigList, err := libcni.LoadConfList(configDir, "some-list")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(len(netConfigList.Plugins)).To(Equal(1))
|
||||||
|
Expect(netConfigList.Plugins[0].Network.Type).To(Equal("bridge"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Context("when the config directory does not exist", func() {
|
Context("when the config directory does not exist", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
Expect(os.RemoveAll(configDir)).To(Succeed())
|
Expect(os.RemoveAll(configDir)).To(Succeed())
|
||||||
@ -191,14 +217,14 @@ var _ = Describe("Loading configuration from disk", func() {
|
|||||||
|
|
||||||
It("returns a useful error", func() {
|
It("returns a useful error", func() {
|
||||||
_, err := libcni.LoadConfList(configDir, "some-plugin")
|
_, err := libcni.LoadConfList(configDir, "some-plugin")
|
||||||
Expect(err).To(MatchError("no net configuration lists found"))
|
Expect(err).To(MatchError("no net configurations found"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("when there is no config for the desired plugin list", func() {
|
Context("when there is no config for the desired plugin list", func() {
|
||||||
It("returns a useful error", func() {
|
It("returns a useful error", func() {
|
||||||
_, err := libcni.LoadConfList(configDir, "some-other-plugin")
|
_, err := libcni.LoadConfList(configDir, "some-other-plugin")
|
||||||
Expect(err).To(MatchError(ContainSubstring(`no net configuration list with name "some-other-plugin" in`)))
|
Expect(err).To(MatchError(libcni.NotFoundError{configDir, "some-other-plugin"}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -233,7 +259,7 @@ var _ = Describe("Loading configuration from disk", func() {
|
|||||||
|
|
||||||
It("will not find the config", func() {
|
It("will not find the config", func() {
|
||||||
_, err := libcni.LoadConfList(configDir, "deep")
|
_, err := libcni.LoadConfList(configDir, "deep")
|
||||||
Expect(err).To(MatchError(HavePrefix("no net configuration list with name")))
|
Expect(err).To(MatchError(HavePrefix("no net configuration with name")))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -339,3 +365,40 @@ var _ = Describe("Loading configuration from disk", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("ConfListFromConf", func() {
|
||||||
|
var testNetConfig *libcni.NetworkConfig
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
pb := []byte(`{"name":"some-plugin","cniVersion":"0.3.0" }`)
|
||||||
|
tc, err := libcni.ConfFromBytes(pb)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
testNetConfig = tc
|
||||||
|
})
|
||||||
|
|
||||||
|
It("correctly upconverts a NetworkConfig to a NetworkConfigList", func() {
|
||||||
|
ncl, err := libcni.ConfListFromConf(testNetConfig)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
bytes := ncl.Bytes
|
||||||
|
|
||||||
|
// null out the json - we don't care about the exact marshalling
|
||||||
|
ncl.Bytes = nil
|
||||||
|
ncl.Plugins[0].Bytes = nil
|
||||||
|
testNetConfig.Bytes = nil
|
||||||
|
|
||||||
|
Expect(ncl).To(Equal(&libcni.NetworkConfigList{
|
||||||
|
Name: "some-plugin",
|
||||||
|
CNIVersion: "0.3.0",
|
||||||
|
Plugins: []*libcni.NetworkConfig{testNetConfig},
|
||||||
|
}))
|
||||||
|
|
||||||
|
//Test that the json unmarshals to the same data
|
||||||
|
ncl2, err := libcni.ConfListFromBytes(bytes)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
ncl2.Bytes = nil
|
||||||
|
ncl2.Plugins[0].Bytes = nil
|
||||||
|
|
||||||
|
Expect(ncl2).To(Equal(ncl))
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user