mirror of https://github.com/k3s-io/k3s
cni: convert "vendor" option to multiple plugin binary search paths
It's only used for the test code and after talking with Rajat, the vendor stuff was never really used anyway. So convert the vendor code into a plain array of plugin binary search paths, which is all the vendor code was doing anyway.pull/8/head
parent
16eaaaed83
commit
69ac723b78
|
@ -118,7 +118,7 @@ func ProbeNetworkPlugins(cniConfDir, cniBinDir string) []network.NetworkPlugin {
|
||||||
allPlugins := []network.NetworkPlugin{}
|
allPlugins := []network.NetworkPlugin{}
|
||||||
|
|
||||||
// for each existing plugin, add to the list
|
// for each existing plugin, add to the list
|
||||||
allPlugins = append(allPlugins, cni.ProbeNetworkPlugins(cniConfDir, cniBinDir)...)
|
allPlugins = append(allPlugins, cni.ProbeNetworkPlugins(cniConfDir, []string{cniBinDir})...)
|
||||||
allPlugins = append(allPlugins, kubenet.NewPlugin(cniBinDir))
|
allPlugins = append(allPlugins, kubenet.NewPlugin(cniBinDir))
|
||||||
|
|
||||||
return allPlugins
|
return allPlugins
|
||||||
|
|
|
@ -229,7 +229,7 @@ func NewDockerService(config *ClientConfig, podSandboxImage string, streamingCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// dockershim currently only supports CNI plugins.
|
// dockershim currently only supports CNI plugins.
|
||||||
cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, pluginSettings.PluginBinDir)
|
cniPlugins := cni.ProbeNetworkPlugins(pluginSettings.PluginConfDir, []string{pluginSettings.PluginBinDir})
|
||||||
cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDir))
|
cniPlugins = append(cniPlugins, kubenet.NewPlugin(pluginSettings.PluginBinDir))
|
||||||
netHost := &dockerNetworkHost{
|
netHost := &dockerNetworkHost{
|
||||||
pluginSettings.LegacyRuntimeHost,
|
pluginSettings.LegacyRuntimeHost,
|
||||||
|
|
|
@ -33,10 +33,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CNIPluginName = "cni"
|
CNIPluginName = "cni"
|
||||||
DefaultConfDir = "/etc/cni/net.d"
|
DefaultConfDir = "/etc/cni/net.d"
|
||||||
DefaultBinDir = "/opt/cni/bin"
|
DefaultBinDir = "/opt/cni/bin"
|
||||||
VendorCNIDirTemplate = "%s/opt/%s/bin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type cniNetworkPlugin struct {
|
type cniNetworkPlugin struct {
|
||||||
|
@ -47,12 +46,11 @@ type cniNetworkPlugin struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
defaultNetwork *cniNetwork
|
defaultNetwork *cniNetwork
|
||||||
|
|
||||||
host network.Host
|
host network.Host
|
||||||
execer utilexec.Interface
|
execer utilexec.Interface
|
||||||
nsenterPath string
|
nsenterPath string
|
||||||
confDir string
|
confDir string
|
||||||
binDir string
|
binDirs []string
|
||||||
vendorCNIDirPrefix string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type cniNetwork struct {
|
type cniNetwork struct {
|
||||||
|
@ -70,17 +68,28 @@ type cniPortMapping struct {
|
||||||
HostIP string `json:"hostIP"`
|
HostIP string `json:"hostIP"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func probeNetworkPluginsWithVendorCNIDirPrefix(confDir, binDir, vendorCNIDirPrefix string) []network.NetworkPlugin {
|
func ProbeNetworkPlugins(confDir string, binDirs []string) []network.NetworkPlugin {
|
||||||
if binDir == "" {
|
old := binDirs
|
||||||
binDir = DefaultBinDir
|
binDirs = make([]string, len(binDirs))
|
||||||
|
for _, dir := range old {
|
||||||
|
if dir != "" {
|
||||||
|
binDirs = append(binDirs, dir)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if len(binDirs) == 0 {
|
||||||
|
binDirs = []string{DefaultBinDir}
|
||||||
|
}
|
||||||
|
|
||||||
|
if confDir == "" {
|
||||||
|
confDir = DefaultConfDir
|
||||||
|
}
|
||||||
|
|
||||||
plugin := &cniNetworkPlugin{
|
plugin := &cniNetworkPlugin{
|
||||||
defaultNetwork: nil,
|
defaultNetwork: nil,
|
||||||
loNetwork: getLoNetwork(binDir, vendorCNIDirPrefix),
|
loNetwork: getLoNetwork(binDirs),
|
||||||
execer: utilexec.New(),
|
execer: utilexec.New(),
|
||||||
confDir: confDir,
|
confDir: confDir,
|
||||||
binDir: binDir,
|
binDirs: binDirs,
|
||||||
vendorCNIDirPrefix: vendorCNIDirPrefix,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync NetworkConfig in best effort during probing.
|
// sync NetworkConfig in best effort during probing.
|
||||||
|
@ -88,14 +97,7 @@ func probeNetworkPluginsWithVendorCNIDirPrefix(confDir, binDir, vendorCNIDirPref
|
||||||
return []network.NetworkPlugin{plugin}
|
return []network.NetworkPlugin{plugin}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProbeNetworkPlugins(confDir, binDir string) []network.NetworkPlugin {
|
func getDefaultCNINetwork(confDir string, binDirs []string) (*cniNetwork, error) {
|
||||||
return probeNetworkPluginsWithVendorCNIDirPrefix(confDir, binDir, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDefaultCNINetwork(confDir, binDir, vendorCNIDirPrefix string) (*cniNetwork, error) {
|
|
||||||
if confDir == "" {
|
|
||||||
confDir = DefaultConfDir
|
|
||||||
}
|
|
||||||
files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"})
|
files, err := libcni.ConfFiles(confDir, []string{".conf", ".conflist", ".json"})
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
|
@ -136,23 +138,17 @@ func getDefaultCNINetwork(confDir, binDir, vendorCNIDirPrefix string) (*cniNetwo
|
||||||
glog.Warningf("CNI config list %s has no networks, skipping", confFile)
|
glog.Warningf("CNI config list %s has no networks, skipping", confFile)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
confType := confList.Plugins[0].Network.Type
|
|
||||||
|
|
||||||
// Search for vendor-specific plugins as well as default plugins in the CNI codebase.
|
network := &cniNetwork{
|
||||||
vendorDir := vendorCNIDir(vendorCNIDirPrefix, confType)
|
name: confList.Name,
|
||||||
cninet := &libcni.CNIConfig{
|
NetworkConfig: confList,
|
||||||
Path: []string{vendorDir, binDir},
|
CNIConfig: &libcni.CNIConfig{Path: binDirs},
|
||||||
}
|
}
|
||||||
network := &cniNetwork{name: confList.Name, NetworkConfig: confList, CNIConfig: cninet}
|
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("No valid networks found in %s", confDir)
|
return nil, fmt.Errorf("No valid networks found in %s", confDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func vendorCNIDir(prefix, pluginType string) string {
|
|
||||||
return fmt.Sprintf(VendorCNIDirTemplate, prefix, pluginType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error {
|
func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error {
|
||||||
err := plugin.platformInit()
|
err := plugin.platformInit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -166,7 +162,7 @@ func (plugin *cniNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *cniNetworkPlugin) syncNetworkConfig() {
|
func (plugin *cniNetworkPlugin) syncNetworkConfig() {
|
||||||
network, err := getDefaultCNINetwork(plugin.confDir, plugin.binDir, plugin.vendorCNIDirPrefix)
|
network, err := getDefaultCNINetwork(plugin.confDir, plugin.binDirs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("Unable to update cni config: %s", err)
|
glog.Warningf("Unable to update cni config: %s", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/kubelet/network"
|
"k8s.io/kubernetes/pkg/kubelet/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork {
|
func getLoNetwork(binDirs []string) *cniNetwork {
|
||||||
loConfig, err := libcni.ConfListFromBytes([]byte(`{
|
loConfig, err := libcni.ConfListFromBytes([]byte(`{
|
||||||
"cniVersion": "0.2.0",
|
"cniVersion": "0.2.0",
|
||||||
"name": "cni-loopback",
|
"name": "cni-loopback",
|
||||||
|
@ -39,13 +39,10 @@ func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork {
|
||||||
// catch this
|
// catch this
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
cninet := &libcni.CNIConfig{
|
|
||||||
Path: []string{vendorCNIDir(vendorDirPrefix, "loopback"), binDir},
|
|
||||||
}
|
|
||||||
loNetwork := &cniNetwork{
|
loNetwork := &cniNetwork{
|
||||||
name: "lo",
|
name: "lo",
|
||||||
NetworkConfig: loConfig,
|
NetworkConfig: loConfig,
|
||||||
CNIConfig: cninet,
|
CNIConfig: &libcni.CNIConfig{Path: binDirs},
|
||||||
}
|
}
|
||||||
|
|
||||||
return loNetwork
|
return loNetwork
|
||||||
|
|
|
@ -47,31 +47,28 @@ import (
|
||||||
fakeexec "k8s.io/utils/exec/testing"
|
fakeexec "k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func installPluginUnderTest(t *testing.T, testVendorCNIDirPrefix, testNetworkConfigPath, vendorName string, plugName string) {
|
// Returns .in file path, .out file path, and .env file path
|
||||||
pluginDir := path.Join(testNetworkConfigPath, plugName)
|
func installPluginUnderTest(t *testing.T, testBinDir, testConfDir, testDataDir, binName string, confName string) (string, string, string) {
|
||||||
err := os.MkdirAll(pluginDir, 0777)
|
for _, dir := range []string{testBinDir, testConfDir, testDataDir} {
|
||||||
if err != nil {
|
err := os.MkdirAll(dir, 0777)
|
||||||
t.Fatalf("Failed to create plugin config dir: %v", err)
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test plugin dir %s: %v", dir, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pluginConfig := path.Join(pluginDir, plugName+".conf")
|
|
||||||
f, err := os.Create(pluginConfig)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to install plugin")
|
|
||||||
}
|
|
||||||
networkConfig := fmt.Sprintf(`{ "name": "%s", "type": "%s", "capabilities": {"portMappings": true} }`, plugName, vendorName)
|
|
||||||
|
|
||||||
|
confFile := path.Join(testConfDir, confName+".conf")
|
||||||
|
f, err := os.Create(confFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to install plugin %s: %v", confFile, err)
|
||||||
|
}
|
||||||
|
networkConfig := fmt.Sprintf(`{ "name": "%s", "type": "%s", "capabilities": {"portMappings": true} }`, confName, binName)
|
||||||
_, err = f.WriteString(networkConfig)
|
_, err = f.WriteString(networkConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to write network config file (%v)", err)
|
t.Fatalf("Failed to write network config file (%v)", err)
|
||||||
}
|
}
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
vendorCNIDir := fmt.Sprintf(VendorCNIDirTemplate, testVendorCNIDirPrefix, vendorName)
|
pluginExec := path.Join(testBinDir, binName)
|
||||||
err = os.MkdirAll(vendorCNIDir, 0777)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create plugin dir: %v", err)
|
|
||||||
}
|
|
||||||
pluginExec := path.Join(vendorCNIDir, vendorName)
|
|
||||||
f, err = os.Create(pluginExec)
|
f, err = os.Create(pluginExec)
|
||||||
|
|
||||||
const execScriptTempl = `#!/bin/bash
|
const execScriptTempl = `#!/bin/bash
|
||||||
|
@ -83,11 +80,14 @@ mkdir -p {{.OutputDir}} &> /dev/null
|
||||||
echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}}
|
echo -n "$CNI_COMMAND $CNI_NETNS $K8S_POD_NAMESPACE $K8S_POD_NAME $K8S_POD_INFRA_CONTAINER_ID" >& {{.OutputFile}}
|
||||||
echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }"
|
echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }"
|
||||||
`
|
`
|
||||||
|
inputFile := path.Join(testDataDir, binName+".in")
|
||||||
|
outputFile := path.Join(testDataDir, binName+".out")
|
||||||
|
envFile := path.Join(testDataDir, binName+".env")
|
||||||
execTemplateData := &map[string]interface{}{
|
execTemplateData := &map[string]interface{}{
|
||||||
"InputFile": path.Join(pluginDir, plugName+".in"),
|
"InputFile": inputFile,
|
||||||
"OutputFile": path.Join(pluginDir, plugName+".out"),
|
"OutputFile": outputFile,
|
||||||
"OutputEnv": path.Join(pluginDir, plugName+".env"),
|
"OutputEnv": envFile,
|
||||||
"OutputDir": pluginDir,
|
"OutputDir": testDataDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
tObj := template.Must(template.New("test").Parse(execScriptTempl))
|
tObj := template.Must(template.New("test").Parse(execScriptTempl))
|
||||||
|
@ -107,6 +107,8 @@ echo -n "{ \"ip4\": { \"ip\": \"10.1.0.23/24\" } }"
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
|
return inputFile, outputFile, envFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func tearDownPlugin(tmpDir string) {
|
func tearDownPlugin(tmpDir string) {
|
||||||
|
@ -155,8 +157,8 @@ func (fnh *fakeNetworkHost) SupportsLegacyFeatures() bool {
|
||||||
|
|
||||||
func TestCNIPlugin(t *testing.T) {
|
func TestCNIPlugin(t *testing.T) {
|
||||||
// install some random plugin
|
// install some random plugin
|
||||||
pluginName := fmt.Sprintf("test%d", rand.Intn(1000))
|
netName := fmt.Sprintf("test%d", rand.Intn(1000))
|
||||||
vendorName := fmt.Sprintf("test_vendor%d", rand.Intn(1000))
|
binName := fmt.Sprintf("test_vendor%d", rand.Intn(1000))
|
||||||
|
|
||||||
podIP := "10.0.0.2"
|
podIP := "10.0.0.2"
|
||||||
podIPOutput := fmt.Sprintf("4: eth0 inet %s/24 scope global dynamic eth0\\ valid_lft forever preferred_lft forever", podIP)
|
podIPOutput := fmt.Sprintf("4: eth0 inet %s/24 scope global dynamic eth0\\ valid_lft forever preferred_lft forever", podIP)
|
||||||
|
@ -183,10 +185,11 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
// TODO mock for the test plugin too
|
// TODO mock for the test plugin too
|
||||||
|
|
||||||
tmpDir := utiltesting.MkTmpdirOrDie("cni-test")
|
tmpDir := utiltesting.MkTmpdirOrDie("cni-test")
|
||||||
testNetworkConfigPath := path.Join(tmpDir, "plugins", "net", "cni")
|
testConfDir := path.Join(tmpDir, "etc", "cni", "net.d")
|
||||||
testVendorCNIDirPrefix := tmpDir
|
testBinDir := path.Join(tmpDir, "opt", "cni", "bin")
|
||||||
|
testDataDir := path.Join(tmpDir, "output")
|
||||||
defer tearDownPlugin(tmpDir)
|
defer tearDownPlugin(tmpDir)
|
||||||
installPluginUnderTest(t, testVendorCNIDirPrefix, testNetworkConfigPath, vendorName, pluginName)
|
inputFile, outputFile, outputEnv := installPluginUnderTest(t, testBinDir, testConfDir, testDataDir, binName, netName)
|
||||||
|
|
||||||
containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"}
|
containerID := kubecontainer.ContainerID{Type: "test", ID: "test_infra_container"}
|
||||||
pods := []*containertest.FakePod{{
|
pods := []*containertest.FakePod{{
|
||||||
|
@ -198,7 +201,7 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
NetnsPath: "/proc/12345/ns/net",
|
NetnsPath: "/proc/12345/ns/net",
|
||||||
}}
|
}}
|
||||||
|
|
||||||
plugins := probeNetworkPluginsWithVendorCNIDirPrefix(path.Join(testNetworkConfigPath, pluginName), "", testVendorCNIDirPrefix)
|
plugins := ProbeNetworkPlugins(testConfDir, []string{testBinDir})
|
||||||
if len(plugins) != 1 {
|
if len(plugins) != 1 {
|
||||||
t.Fatalf("Expected only one network plugin, got %d", len(plugins))
|
t.Fatalf("Expected only one network plugin, got %d", len(plugins))
|
||||||
}
|
}
|
||||||
|
@ -238,9 +241,7 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expected nil: %v", err)
|
t.Errorf("Expected nil: %v", err)
|
||||||
}
|
}
|
||||||
outputEnv := path.Join(testNetworkConfigPath, pluginName, pluginName+".env")
|
|
||||||
eo, eerr := ioutil.ReadFile(outputEnv)
|
eo, eerr := ioutil.ReadFile(outputEnv)
|
||||||
outputFile := path.Join(testNetworkConfigPath, pluginName, pluginName+".out")
|
|
||||||
output, err := ioutil.ReadFile(outputFile)
|
output, err := ioutil.ReadFile(outputFile)
|
||||||
if err != nil || eerr != nil {
|
if err != nil || eerr != nil {
|
||||||
t.Errorf("Failed to read output file %s: %v (env %s err %v)", outputFile, err, eo, eerr)
|
t.Errorf("Failed to read output file %s: %v (env %s err %v)", outputFile, err, eo, eerr)
|
||||||
|
@ -257,7 +258,6 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
PortMappings []map[string]interface{} `json:"portMappings"`
|
PortMappings []map[string]interface{} `json:"portMappings"`
|
||||||
} `json:"runtimeConfig"`
|
} `json:"runtimeConfig"`
|
||||||
}{}
|
}{}
|
||||||
inputFile := path.Join(testNetworkConfigPath, pluginName, pluginName+".in")
|
|
||||||
inputBytes, inerr := ioutil.ReadFile(inputFile)
|
inputBytes, inerr := ioutil.ReadFile(inputFile)
|
||||||
parseerr := json.Unmarshal(inputBytes, &inputConfig)
|
parseerr := json.Unmarshal(inputBytes, &inputConfig)
|
||||||
if inerr != nil || parseerr != nil {
|
if inerr != nil || parseerr != nil {
|
||||||
|
@ -285,7 +285,7 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expected nil: %v", err)
|
t.Errorf("Expected nil: %v", err)
|
||||||
}
|
}
|
||||||
output, err = ioutil.ReadFile(path.Join(testNetworkConfigPath, pluginName, pluginName+".out"))
|
output, err = ioutil.ReadFile(outputFile)
|
||||||
expectedOutput = "DEL /proc/12345/ns/net podNamespace podName test_infra_container"
|
expectedOutput = "DEL /proc/12345/ns/net podNamespace podName test_infra_container"
|
||||||
if string(output) != expectedOutput {
|
if string(output) != expectedOutput {
|
||||||
t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output))
|
t.Errorf("Mismatch in expected output for setup hook. Expected '%s', got '%s'", expectedOutput, string(output))
|
||||||
|
@ -295,7 +295,7 @@ func TestCNIPlugin(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoNetNonNil(t *testing.T) {
|
func TestLoNetNonNil(t *testing.T) {
|
||||||
if conf := getLoNetwork("", ""); conf == nil {
|
if conf := getLoNetwork(nil); conf == nil {
|
||||||
t.Error("Expected non-nil lo network")
|
t.Error("Expected non-nil lo network")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/kubelet/network"
|
"k8s.io/kubernetes/pkg/kubelet/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getLoNetwork(binDir, vendorDirPrefix string) *cniNetwork {
|
func getLoNetwork(binDirs []string) *cniNetwork {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue