From 2745e46ed81713fa714a5303117ee5bcc3caeae0 Mon Sep 17 00:00:00 2001 From: Tomofumi Hayashi Date: Mon, 19 Aug 2019 17:17:51 +0900 Subject: [PATCH] Support 'cni-args' in NetworkSelectionElement --- k8sclient/k8sclient.go | 4 -- types/conf.go | 84 +++++++++++++++++++++++++++++++++ types/conf_test.go | 104 +++++++++++++++++++++++++++++++++++++++++ types/types.go | 2 + 4 files changed, 190 insertions(+), 4 deletions(-) diff --git a/k8sclient/k8sclient.go b/k8sclient/k8sclient.go index 1c9a0264a..9a6f54b55 100644 --- a/k8sclient/k8sclient.go +++ b/k8sclient/k8sclient.go @@ -233,10 +233,6 @@ func parsePodNetworkAnnotation(podNetworks, defaultNamespace string) ([]*types.N if n.Namespace == "" { n.Namespace = defaultNamespace } - // compatibility pre v3.2, will be removed in v4.0 - if n.DeprecatedInterfaceRequest != "" && n.InterfaceRequest == "" { - n.InterfaceRequest = n.DeprecatedInterfaceRequest - } if n.MacRequest != "" { // validate MAC address if _, err := net.ParseMAC(n.MacRequest); err != nil { diff --git a/types/conf.go b/types/conf.go index 2944f7fec..a44c419a7 100644 --- a/types/conf.go +++ b/types/conf.go @@ -74,6 +74,12 @@ func LoadDelegateNetConf(bytes []byte, net *NetworkSelectionElement, deviceID st return nil, logging.Errorf("LoadDelegateNetConf: failed to add deviceID in NetConfList bytes: %v", err) } } + if net != nil && net.CNIArgs != nil { + bytes, err = addCNIArgsInConfList(bytes, net.CNIArgs) + if err != nil { + return nil, logging.Errorf("LoadDelegateNetConf(): failed to add cni-args in NetConfList bytes: %v", err) + } + } } else { if deviceID != "" { bytes, err = delegateAddDeviceID(bytes, deviceID) @@ -81,6 +87,12 @@ func LoadDelegateNetConf(bytes []byte, net *NetworkSelectionElement, deviceID st return nil, logging.Errorf("LoadDelegateNetConf: failed to add deviceID in NetConf bytes: %v", err) } } + if net != nil && net.CNIArgs != nil { + bytes, err = addCNIArgsInConfig(bytes, net.CNIArgs) + if err != nil { + return nil, logging.Errorf("LoadDelegateNetConf(): failed to add cni-args in NetConfList bytes: %v", err) + } + } } if net != nil { @@ -365,6 +377,78 @@ func addDeviceIDInConfList(inBytes []byte, deviceID string) ([]byte, error) { return configBytes, nil } +// injectCNIArgs injects given args to cniConfig +func injectCNIArgs(cniConfig *map[string]interface{}, args *map[string]interface{}) error { + if argsval, ok := (*cniConfig)["args"]; ok { + argsvalmap := argsval.(map[string]interface{}) + if cnival, ok := argsvalmap["cni"]; ok { + cnivalmap := cnival.(map[string]interface{}) + // merge it if conf has args + for key, val := range *args { + cnivalmap[key] = val + } + } else { + argsvalmap["cni"] = *args + } + } else { + argsval := map[string]interface{}{} + argsval["cni"] = *args + (*cniConfig)["args"] = argsval + } + return nil +} + +// addCNIArgsInConfig injects given cniArgs to CNI config in inBytes +func addCNIArgsInConfig(inBytes []byte, cniArgs *map[string]interface{}) ([]byte, error) { + var rawConfig map[string]interface{} + var err error + + err = json.Unmarshal(inBytes, &rawConfig) + if err != nil { + return nil, logging.Errorf("addCNIArgsInConfig(): failed to unmarshal inBytes: %v", err) + } + + injectCNIArgs(&rawConfig, cniArgs) + + configBytes, err := json.Marshal(rawConfig) + if err != nil { + return nil, logging.Errorf("addCNIArgsInConfig(): failed to re-marshal: %v", err) + } + return configBytes, nil +} + +// addCNIArgsInConfList injects given cniArgs to CNI conflist in inBytes +func addCNIArgsInConfList(inBytes []byte, cniArgs *map[string]interface{}) ([]byte, error) { + var rawConfig map[string]interface{} + var err error + + err = json.Unmarshal(inBytes, &rawConfig) + if err != nil { + return nil, logging.Errorf("addCNIArgsInConfList(): failed to unmarshal inBytes: %v", err) + } + + pList, ok := rawConfig["plugins"] + if !ok { + return nil, logging.Errorf("addCNIArgsInConfList(): unable to get plugin list") + } + + pMap, ok := pList.([]interface{}) + if !ok { + return nil, logging.Errorf("addCNIArgsInConfList(): unable to typecast plugin list") + } + + for idx := range pMap { + valMap := pMap[idx].(map[string]interface{}) + injectCNIArgs(&valMap, cniArgs) + } + + configBytes, err := json.Marshal(rawConfig) + if err != nil { + return nil, logging.Errorf("addCNIArgsInConfList(): failed to re-marshal: %v", err) + } + return configBytes, nil +} + // CheckSystemNamespaces checks whether given namespace is in systemNamespaces or not. func CheckSystemNamespaces(namespace string, systemNamespaces []string) bool { for _, nsname := range systemNamespaces { diff --git a/types/conf_test.go b/types/conf_test.go index 3111e6112..8d456c7d5 100644 --- a/types/conf_test.go +++ b/types/conf_test.go @@ -358,6 +358,110 @@ var _ = Describe("config operations", func() { Expect(hostDeviceConfList.Plugins[0].PCIBusID).To(Equal("0000:00:00.3")) }) + It("add cni-args in config", func() { + var args map[string]interface{} + conf := `{ + "name": "second-network", + "type": "bridge" +}` + cniArgs := `{ + "args1": "val1" +}` + type bridgeNetConf struct { + Name string `json:"name"` + Type string `json:"type"` + Args struct { + CNI map[string]string `json:"cni"` + } `json:"args"` + } + + err := json.Unmarshal([]byte(cniArgs), &args) + Expect(err).NotTo(HaveOccurred()) + net := &NetworkSelectionElement{ + Name: "test-elem", + CNIArgs: &args, + } + delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "") + Expect(err).NotTo(HaveOccurred()) + bridgeConf := &bridgeNetConf{} + err = json.Unmarshal(delegateNetConf.Bytes, bridgeConf) + Expect(bridgeConf.Args.CNI["args1"]).To(Equal("val1")) + }) + + It("add cni-args in config which has cni args already (merge case)", func() { + var args map[string]interface{} + conf := `{ + "name": "second-network", + "type": "bridge", + "args": { + "cni": { + "args0": "val0", + "args1": "val1" + } + } +}` + cniArgs := `{ + "args1": "val1a" +}` + type bridgeNetConf struct { + Name string `json:"name"` + Type string `json:"type"` + Args struct { + CNI map[string]string `json:"cni"` + } `json:"args"` + } + + err := json.Unmarshal([]byte(cniArgs), &args) + Expect(err).NotTo(HaveOccurred()) + net := &NetworkSelectionElement{ + Name: "test-elem", + CNIArgs: &args, + } + delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "") + Expect(err).NotTo(HaveOccurred()) + bridgeConf := &bridgeNetConf{} + err = json.Unmarshal(delegateNetConf.Bytes, bridgeConf) + Expect(bridgeConf.Args.CNI["args0"]).To(Equal("val0")) + Expect(bridgeConf.Args.CNI["args1"]).To(Equal("val1a")) + }) + + It("add cni-args in conflist", func() { + var args map[string]interface{} + conf := `{ + "name": "second-network", + "plugins": [ + { + "type": "bridge" + } + ] +}` + cniArgs := `{ + "args1": "val1" +}` + type bridgeNetConf struct { + Type string `json:"type"` + Args struct { + CNI map[string]string `json:"cni"` + } `json:"args"` + } + type bridgeNetConfList struct { + Name string `json:"name"` + Plugins []*bridgeNetConf `json:"plugins"` + } + + err := json.Unmarshal([]byte(cniArgs), &args) + Expect(err).NotTo(HaveOccurred()) + net := &NetworkSelectionElement{ + Name: "test-elem", + CNIArgs: &args, + } + delegateNetConf, err := LoadDelegateNetConf([]byte(conf), net, "") + Expect(err).NotTo(HaveOccurred()) + bridgeConflist := &bridgeNetConfList{} + err = json.Unmarshal(delegateNetConf.Bytes, bridgeConflist) + Expect(bridgeConflist.Plugins[0].Args.CNI["args1"]).To(Equal("val1")) + }) + It("creates a valid CNI runtime config", func() { args := &skel.CmdArgs{ ContainerID: "123456789", diff --git a/types/types.go b/types/types.go index 693b98084..803ae1e64 100644 --- a/types/types.go +++ b/types/types.go @@ -163,6 +163,8 @@ type NetworkSelectionElement struct { // BandwidthRequest contains an optional requested bandwidth for // the network BandwidthRequest *BandwidthEntry `json:"bandwidth,omitempty"` + // CNIArgs contains additional CNI arguments for the network interface + CNIArgs *map[string]interface{} `json:"cni-args"` } // K8sArgs is the valid CNI_ARGS used for Kubernetes