From 4974be4b20f45f8be74eaa77e105febc856afa2f Mon Sep 17 00:00:00 2001 From: giovanism Date: Sat, 24 Aug 2019 16:52:42 +0700 Subject: [PATCH] rook: Move network util functions to k8sutil rook: Remove NetworkSelector type alias rook: Add error return value for multus funcs Signed-off-by: giovanism --- pkg/apis/rook.io/v1alpha2/network.go | 93 ------------- pkg/apis/rook.io/v1alpha2/network_test.go | 86 +----------- pkg/apis/rook.io/v1alpha2/types.go | 4 +- .../rook.io/v1alpha2/zz_generated.deepcopy.go | 2 +- pkg/operator/edgefs/cluster/configmap.go | 51 ++++--- pkg/operator/edgefs/cluster/mgr/mgr.go | 2 +- pkg/operator/edgefs/cluster/mgr/mgr_test.go | 2 +- pkg/operator/edgefs/cluster/target/pod.go | 5 +- pkg/operator/edgefs/iscsi/iscsi.go | 3 +- pkg/operator/edgefs/nfs/nfs.go | 3 +- pkg/operator/edgefs/s3/s3.go | 3 +- pkg/operator/edgefs/s3x/s3x.go | 3 +- pkg/operator/k8sutil/network.go | 121 +++++++++++++++++ pkg/operator/k8sutil/network_test.go | 126 ++++++++++++++++++ 14 files changed, 292 insertions(+), 212 deletions(-) create mode 100644 pkg/operator/k8sutil/network.go create mode 100644 pkg/operator/k8sutil/network_test.go diff --git a/pkg/apis/rook.io/v1alpha2/network.go b/pkg/apis/rook.io/v1alpha2/network.go index 10b705ff7..5a5c9ffde 100644 --- a/pkg/apis/rook.io/v1alpha2/network.go +++ b/pkg/apis/rook.io/v1alpha2/network.go @@ -16,13 +16,6 @@ limitations under the License. package v1alpha2 -import ( - "encoding/json" - "strings" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - // IsHost get whether to use host network provider func (net *NetworkSpec) IsHost() bool { return net.Provider == "host" @@ -32,89 +25,3 @@ func (net *NetworkSpec) IsHost() bool { func (net *NetworkSpec) IsMultus() bool { return net.Provider == "multus" } - -// parseMultusSelector will parse short and JSON form of individual multus -// network attachment selection annotation. Valid JSON will be unmarshaled and -// return as is, while invalid JSON will be tried using -// /@ short syntax. -// BUG(giovanism): There are no data (name, interface, namespace) validation -func parseMultusSelector(ns NetworkSelector) map[string]string { - rawMap := make(map[string]string) - - err := json.Unmarshal([]byte(ns), &rawMap) - - if err != nil { - // it can be in short form - multusSelectorString := string(ns) - - nsEndIndex := strings.IndexAny(multusSelectorString, "/") - if nsEndIndex != -1 { - rawMap["namespace"] = multusSelectorString[:nsEndIndex] - } - - ifStartIndex := strings.LastIndexAny(multusSelectorString, "@") - if ifStartIndex != -1 && len(multusSelectorString)-ifStartIndex > 1 { - rawMap["interface"] = multusSelectorString[ifStartIndex+1:] - } - - if nsEndIndex != -1 && ifStartIndex != -1 && ifStartIndex-nsEndIndex > 1 { - rawMap["name"] = multusSelectorString[nsEndIndex+1 : ifStartIndex] - } else if nsEndIndex == -1 && ifStartIndex != -1 { - rawMap["name"] = multusSelectorString[:ifStartIndex] - } else if nsEndIndex != -1 && ifStartIndex == -1 { - rawMap["name"] = multusSelectorString[nsEndIndex+1:] - } - } - - return rawMap -} - -// GetMultusIfName return a network interface name that multus will assign when -// connected to the multus network. -// BUG(giovanism): Can't relliably tell the network interface name using a -// network selector alone if the interface name is omitted. -func GetMultusIfName(ns NetworkSelector) string { - multusMap := parseMultusSelector(ns) - ifName := "net1" - - if name, ok := multusMap["interfaceRequest"]; ok { - ifName = name - } - if name, ok := multusMap["interface"]; ok { - ifName = name - } - - return ifName -} - -// ApplyMultus apply multus selector to Pods -// Multus supports short and json syntax, use only one kind at a time. -// BUG(giovanism): Can't mix short and JSON form of multus network selection -// annotation. -func ApplyMultus(net NetworkSpec, objectMeta *metav1.ObjectMeta) { - v := make([]string, 0, 2) - useSquareBrackets := false - - for _, ns := range net.Selectors { - if !useSquareBrackets { - var multusMap map[string]string - err := json.Unmarshal([]byte(ns), &multusMap) - - if err == nil { - useSquareBrackets = true - } - } - - v = append(v, string(ns)) - } - - networks := strings.Join(v, ", ") - if useSquareBrackets { - networks = "[" + networks + "]" - } - - t := Annotations{ - "k8s.v1.cni.cncf.io/networks": networks, - } - t.ApplyToObjectMeta(objectMeta) -} diff --git a/pkg/apis/rook.io/v1alpha2/network_test.go b/pkg/apis/rook.io/v1alpha2/network_test.go index 632734178..e0a623e3b 100644 --- a/pkg/apis/rook.io/v1alpha2/network_test.go +++ b/pkg/apis/rook.io/v1alpha2/network_test.go @@ -22,7 +22,6 @@ import ( "github.com/ghodss/yaml" "github.com/stretchr/testify/assert" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestNetwork_Spec(t *testing.T) { @@ -42,90 +41,11 @@ selectors: expected := NetworkSpec{ Provider: "host", - Selectors: map[string]NetworkSelector{ - "server": NetworkSelector("enp2s0f0"), - "broker": NetworkSelector("enp2s0f0"), + Selectors: map[string]string{ + "server": "enp2s0f0", + "broker": "enp2s0f0", }, } assert.Equal(t, expected, net) } - -func TestNetwork_GetMultusIfName(t *testing.T) { - multusSelector := NetworkSelector("macvlan@server1") - ifName := GetMultusIfName(multusSelector) - - assert.Equal(t, "server1", ifName) -} - -func TestNetwork_GetMultusIfNameDefault(t *testing.T) { - multusSelector := NetworkSelector("macvlan") - ifName := GetMultusIfName(multusSelector) - - assert.Equal(t, "net1", ifName) -} - -func TestNetwork_parseMultusSelectorJSON(t *testing.T) { - multusSelector := NetworkSelector(`{ - "name": "macvlan", - "interface": "server1", - "namespace": "rook-edgefs" - }`) - - multusMap := parseMultusSelector(multusSelector) - - expected := map[string]string{ - "name": "macvlan", - "interface": "server1", - "namespace": "rook-edgefs", - } - - assert.Equal(t, expected, multusMap) -} - -func TestNetwork_parseMultusSelectorShort(t *testing.T) { - multusSelector := NetworkSelector("rook-edgefs/macvlan@server1") - multusMap := parseMultusSelector(multusSelector) - - expected := map[string]string{ - "name": "macvlan", - "interface": "server1", - "namespace": "rook-edgefs", - } - - assert.Equal(t, expected, multusMap) -} - -func TestNetwork_ApplyMultusShort(t *testing.T) { - net := NetworkSpec{ - Provider: "multus", - Selectors: map[string]NetworkSelector{ - "server": "macvlan@net1", - "broker": "macvlan@net2", - }, - } - - objMeta := metav1.ObjectMeta{} - ApplyMultus(net, &objMeta) - - assert.Contains(t, objMeta.Annotations, "k8s.v1.cni.cncf.io/networks") - assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], "macvlan@net1") - assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], "macvlan@net2") -} - -func TestNetwork_ApplyMultusJSON(t *testing.T) { - net := NetworkSpec{ - Provider: "multus", - Selectors: map[string]NetworkSelector{ - "server": `{"name": "macvlan", "interface": "net1"}`, - "broker": `{"name": "macvlan", "interface": "net2"}`, - }, - } - - objMeta := metav1.ObjectMeta{} - ApplyMultus(net, &objMeta) - - assert.Contains(t, objMeta.Annotations, "k8s.v1.cni.cncf.io/networks") - assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], `{"name": "macvlan", "interface": "net1"}`) - assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], `{"name": "macvlan", "interface": "net2"}`) -} diff --git a/pkg/apis/rook.io/v1alpha2/types.go b/pkg/apis/rook.io/v1alpha2/types.go index f26a43958..6b5373805 100644 --- a/pkg/apis/rook.io/v1alpha2/types.go +++ b/pkg/apis/rook.io/v1alpha2/types.go @@ -81,8 +81,6 @@ type Placement struct { type ResourceSpec map[string]v1.ResourceRequirements -type NetworkSelector string - // NetworkSpec represents cluster network settings type NetworkSpec struct { // Provider is what provides network connectivity to the cluster e.g. "host" or "multus" @@ -91,7 +89,7 @@ type NetworkSpec struct { // Selectors string values describe what networks will be used to connect the cluster. // Meanwhile the keys describe each network respective responsibilities or any metadata // storage provider decide. - Selectors map[string]NetworkSelector `json:"selectors"` + Selectors map[string]string `json:"selectors"` } // +genclient diff --git a/pkg/apis/rook.io/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/rook.io/v1alpha2/zz_generated.deepcopy.go index f445b1a3a..5993e98ea 100644 --- a/pkg/apis/rook.io/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/rook.io/v1alpha2/zz_generated.deepcopy.go @@ -146,7 +146,7 @@ func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { *out = *in if in.Selectors != nil { in, out := &in.Selectors, &out.Selectors - *out = make(map[string]NetworkSelector, len(*in)) + *out = make(map[string]string, len(*in)) for key, val := range *in { (*out)[key] = val } diff --git a/pkg/operator/edgefs/cluster/configmap.go b/pkg/operator/edgefs/cluster/configmap.go index b61e722cd..eb521cbdf 100644 --- a/pkg/operator/edgefs/cluster/configmap.go +++ b/pkg/operator/edgefs/cluster/configmap.go @@ -20,7 +20,6 @@ import ( "encoding/json" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/operator/edgefs/cluster/target" "github.com/rook/rook/pkg/operator/k8sutil" v1 "k8s.io/api/core/v1" @@ -49,33 +48,47 @@ func (c *cluster) createClusterConfigMap(deploymentConfig edgefsv1beta1.ClusterD serverIfName := defaultServerIfName brokerIfName := defaultBrokerIfName - if c.Spec.Network.IsHost() { - serverSelector, serverDefined := c.Spec.Network.Selectors["server"] - brokerSelector, brokerDefined := c.Spec.Network.Selectors["broker"] + serverSelector, serverDefined := c.Spec.Network.Selectors["server"] + brokerSelector, brokerDefined := c.Spec.Network.Selectors["broker"] + + if c.Spec.Network.IsHost() { if serverDefined && brokerDefined { - serverIfName = string(serverSelector) - brokerIfName = string(brokerSelector) + serverIfName = serverSelector + brokerIfName = brokerSelector } else if serverDefined { - serverIfName = string(serverSelector) - brokerIfName = string(serverSelector) + serverIfName = serverSelector + brokerIfName = serverSelector } else if brokerDefined { - serverIfName = string(brokerSelector) - brokerIfName = string(brokerSelector) + serverIfName = brokerSelector + brokerIfName = brokerSelector } } else if c.Spec.Network.IsMultus() { - serverSelector, serverDefined := c.Spec.Network.Selectors["server"] - brokerSelector, brokerDefined := c.Spec.Network.Selectors["broker"] - if serverDefined && brokerDefined { - serverIfName = rookalpha.GetMultusIfName(serverSelector) - brokerIfName = rookalpha.GetMultusIfName(brokerSelector) + var err error + serverIfName, err = k8sutil.GetMultusIfName(serverSelector) + if err != nil { + return err + } + + brokerIfName, err = k8sutil.GetMultusIfName(brokerSelector) + if err != nil { + return err + } } else if serverDefined { - serverIfName = rookalpha.GetMultusIfName(serverSelector) - brokerIfName = rookalpha.GetMultusIfName(serverSelector) + serverIfName, err := k8sutil.GetMultusIfName(serverSelector) + if err != nil { + return err + } + + brokerIfName = serverIfName } else if brokerDefined { - serverIfName = rookalpha.GetMultusIfName(brokerSelector) - brokerIfName = rookalpha.GetMultusIfName(brokerSelector) + serverIfName, err := k8sutil.GetMultusIfName(brokerSelector) + if err != nil { + return err + } + + brokerIfName = serverIfName } } diff --git a/pkg/operator/edgefs/cluster/mgr/mgr.go b/pkg/operator/edgefs/cluster/mgr/mgr.go index 951542acf..87a089c0f 100644 --- a/pkg/operator/edgefs/cluster/mgr/mgr.go +++ b/pkg/operator/edgefs/cluster/mgr/mgr.go @@ -344,7 +344,7 @@ func (c *Cluster) makeDeployment(name, clusterName, rookImage string, replicas i if c.NetworkSpec.IsHost() { podSpec.Spec.DNSPolicy = v1.DNSClusterFirstWithHostNet } else if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) } c.annotations.ApplyToObjectMeta(&podSpec.ObjectMeta) diff --git a/pkg/operator/edgefs/cluster/mgr/mgr_test.go b/pkg/operator/edgefs/cluster/mgr/mgr_test.go index e545df7da..babd0cac3 100644 --- a/pkg/operator/edgefs/cluster/mgr/mgr_test.go +++ b/pkg/operator/edgefs/cluster/mgr/mgr_test.go @@ -122,7 +122,7 @@ func TestHostNetwork(t *testing.T) { volSize := resource.NewQuantity(100000.0, resource.BinarySI) net := rookalpha.NetworkSpec{ Provider: "host", - Selectors: map[string]rookalpha.NetworkSelector{ + Selectors: map[string]string{ "server": "eth0", }, } diff --git a/pkg/operator/edgefs/cluster/target/pod.go b/pkg/operator/edgefs/cluster/target/pod.go index 3cf129033..f1e89898a 100644 --- a/pkg/operator/edgefs/cluster/target/pod.go +++ b/pkg/operator/edgefs/cluster/target/pod.go @@ -21,7 +21,6 @@ import ( "strconv" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/operator/edgefs/cluster/target/config" "github.com/rook/rook/pkg/operator/k8sutil" appsv1 "k8s.io/api/apps/v1" @@ -565,8 +564,8 @@ func (c *Cluster) makeStatefulSet(replicas int32, rookImage string, dro edgefsv1 k8sutil.SetOwnerRef(&statefulSet.ObjectMeta, &c.ownerRef) if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &statefulSet.ObjectMeta) - rookalpha.ApplyMultus(c.NetworkSpec, &statefulSet.Spec.Template.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &statefulSet.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &statefulSet.Spec.Template.ObjectMeta) } c.annotations.ApplyToObjectMeta(&statefulSet.ObjectMeta) c.annotations.ApplyToObjectMeta(&statefulSet.Spec.Template.ObjectMeta) diff --git a/pkg/operator/edgefs/iscsi/iscsi.go b/pkg/operator/edgefs/iscsi/iscsi.go index 30be46b70..32a13c987 100644 --- a/pkg/operator/edgefs/iscsi/iscsi.go +++ b/pkg/operator/edgefs/iscsi/iscsi.go @@ -22,7 +22,6 @@ import ( "fmt" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/clusterd" "github.com/rook/rook/pkg/operator/k8sutil" apps "k8s.io/api/apps/v1" @@ -177,7 +176,7 @@ func (c *ISCSIController) makeDeployment(svcname, namespace, rookImage string, i if c.NetworkSpec.IsHost() { podSpec.Spec.DNSPolicy = v1.DNSClusterFirstWithHostNet } else if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) } iscsiSpec.Annotations.ApplyToObjectMeta(&podSpec.ObjectMeta) diff --git a/pkg/operator/edgefs/nfs/nfs.go b/pkg/operator/edgefs/nfs/nfs.go index bb2671a30..fa9c79dbe 100644 --- a/pkg/operator/edgefs/nfs/nfs.go +++ b/pkg/operator/edgefs/nfs/nfs.go @@ -21,7 +21,6 @@ import ( "fmt" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/clusterd" "github.com/rook/rook/pkg/operator/k8sutil" apps "k8s.io/api/apps/v1" @@ -181,7 +180,7 @@ func (c *NFSController) makeDeployment(svcname, namespace, rookImage string, nfs if c.NetworkSpec.IsHost() { podSpec.Spec.DNSPolicy = v1.DNSClusterFirstWithHostNet } else if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) } nfsSpec.Annotations.ApplyToObjectMeta(&podSpec.ObjectMeta) diff --git a/pkg/operator/edgefs/s3/s3.go b/pkg/operator/edgefs/s3/s3.go index 10f927500..07afb185e 100644 --- a/pkg/operator/edgefs/s3/s3.go +++ b/pkg/operator/edgefs/s3/s3.go @@ -22,7 +22,6 @@ import ( "strings" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/clusterd" "github.com/rook/rook/pkg/operator/k8sutil" apps "k8s.io/api/apps/v1" @@ -246,7 +245,7 @@ func (c *S3Controller) makeDeployment(svcname, namespace, rookImage, imageArgs s if c.NetworkSpec.IsHost() { podSpec.Spec.DNSPolicy = v1.DNSClusterFirstWithHostNet } else if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) } // apply current S3 CRD options to pod's specification diff --git a/pkg/operator/edgefs/s3x/s3x.go b/pkg/operator/edgefs/s3x/s3x.go index 0c148a391..f47e5ff57 100644 --- a/pkg/operator/edgefs/s3x/s3x.go +++ b/pkg/operator/edgefs/s3x/s3x.go @@ -22,7 +22,6 @@ import ( "strings" edgefsv1beta1 "github.com/rook/rook/pkg/apis/edgefs.rook.io/v1beta1" - rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" "github.com/rook/rook/pkg/clusterd" "github.com/rook/rook/pkg/operator/k8sutil" apps "k8s.io/api/apps/v1" @@ -230,7 +229,7 @@ func (c *S3XController) makeDeployment(svcname, namespace, rookImage string, s3x if c.NetworkSpec.IsHost() { podSpec.Spec.DNSPolicy = v1.DNSClusterFirstWithHostNet } else if c.NetworkSpec.IsMultus() { - rookalpha.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) + k8sutil.ApplyMultus(c.NetworkSpec, &podSpec.ObjectMeta) } // apply current S3X CRD options to pod's specification diff --git a/pkg/operator/k8sutil/network.go b/pkg/operator/k8sutil/network.go new file mode 100644 index 000000000..3235093f5 --- /dev/null +++ b/pkg/operator/k8sutil/network.go @@ -0,0 +1,121 @@ +/* +Copyright 2019 The Rook Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +    http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package k8sutil + +import ( + "encoding/json" + "fmt" + "strings" + + rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// parseMultusSelector will parse short and JSON form of individual multus +// network attachment selection annotation. Valid JSON will be unmarshaled and +// return as is, while invalid JSON will be tried using +// /@ short syntax. +func parseMultusSelector(selector string) (map[string]string, error) { + rawMap := make(map[string]string) + + err := json.Unmarshal([]byte(selector), &rawMap) + + if err != nil { + // it can be in short form + nsEndIndex := strings.IndexAny(selector, "/") + if nsEndIndex != -1 { + rawMap["namespace"] = selector[:nsEndIndex] + } + + ifStartIndex := strings.LastIndexAny(selector, "@") + if ifStartIndex != -1 && len(selector)-ifStartIndex > 1 { + rawMap["interface"] = selector[ifStartIndex+1:] + } + + if nsEndIndex != -1 && ifStartIndex != -1 && ifStartIndex-nsEndIndex > 1 { + rawMap["name"] = selector[nsEndIndex+1 : ifStartIndex] + } else if nsEndIndex == -1 && ifStartIndex != -1 { + rawMap["name"] = selector[:ifStartIndex] + } else if nsEndIndex != -1 && ifStartIndex == -1 { + rawMap["name"] = selector[nsEndIndex+1:] + } + } + + if name, ok := rawMap["name"]; !ok || name == "" { + return nil, fmt.Errorf("parseMultusSelector: missing name") + } + + return rawMap, nil +} + +// GetMultusIfName return a network interface name that multus will assign when +// connected to the multus network. +func GetMultusIfName(selector string) (string, error) { + multusMap, _ := parseMultusSelector(selector) + var ifName string + + if name, ok := multusMap["interfaceRequest"]; ok { + ifName = name + } + if name, ok := multusMap["interface"]; ok { + ifName = name + } + + // fail selector without inteface name + if ifName == "" { + return "", fmt.Errorf("GetMultusIfname: missing interface") + } + + return ifName, nil +} + +// ApplyMultus apply multus selector to Pods +// Multus supports short and json syntax, use only one kind at a time. +func ApplyMultus(net rookalpha.NetworkSpec, objectMeta *metav1.ObjectMeta) error { + v := make([]string, 0, 2) + shortSyntax := false + jsonSyntax := false + + for _, ns := range net.Selectors { + var multusMap map[string]string + err := json.Unmarshal([]byte(ns), &multusMap) + + if err == nil { + jsonSyntax = true + } else { + shortSyntax = true + } + + v = append(v, string(ns)) + } + + if shortSyntax && jsonSyntax { + return fmt.Errorf("ApplyMultus: Can't mix short and JSON form") + } + + networks := strings.Join(v, ", ") + if jsonSyntax { + networks = "[" + networks + "]" + } + + t := rookalpha.Annotations{ + "k8s.v1.cni.cncf.io/networks": networks, + } + t.ApplyToObjectMeta(objectMeta) + + return nil +} diff --git a/pkg/operator/k8sutil/network_test.go b/pkg/operator/k8sutil/network_test.go new file mode 100644 index 000000000..aed690e0a --- /dev/null +++ b/pkg/operator/k8sutil/network_test.go @@ -0,0 +1,126 @@ +/* +Copyright 2019 The Rook Authors. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package k8sutil + +import ( + "testing" + + rookalpha "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestNetwork_GetMultusIfName(t *testing.T) { + multusSelector := "macvlan@server1" + ifName, _ := GetMultusIfName(multusSelector) + + assert.Equal(t, "server1", ifName) +} + +func TestNetwork_GetMultusIfNameDefault(t *testing.T) { + multusSelector := "macvlan" + _, err := GetMultusIfName(multusSelector) + + assert.Error(t, err) +} + +func TestNetwork_parseMultusSelectorJSON(t *testing.T) { + multusSelector := `{ + "name": "macvlan", + "interface": "server1", + "namespace": "rook-edgefs" + }` + + multusMap, _ := parseMultusSelector(multusSelector) + + expected := map[string]string{ + "name": "macvlan", + "interface": "server1", + "namespace": "rook-edgefs", + } + + assert.Equal(t, expected, multusMap) +} + +func TestNetwork_parseMultusSelectorShort(t *testing.T) { + multusSelector := "rook-edgefs/macvlan@server1" + multusMap, _ := parseMultusSelector(multusSelector) + + expected := map[string]string{ + "name": "macvlan", + "interface": "server1", + "namespace": "rook-edgefs", + } + + assert.Equal(t, expected, multusMap) +} + +func TestNetwork_parseMultusSelectorError(t *testing.T) { + multusSelector := "rook-edgefs/@server1" + _, err := parseMultusSelector(multusSelector) + + assert.Error(t, err) +} + +func TestNetwork_ApplyMultusShort(t *testing.T) { + net := rookalpha.NetworkSpec{ + Provider: "multus", + Selectors: map[string]string{ + "server": "macvlan@net1", + "broker": "macvlan@net2", + }, + } + + objMeta := metav1.ObjectMeta{} + ApplyMultus(net, &objMeta) + + assert.Contains(t, objMeta.Annotations, "k8s.v1.cni.cncf.io/networks") + assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], "macvlan@net1") + assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], "macvlan@net2") +} + +func TestNetwork_ApplyMultusJSON(t *testing.T) { + net := rookalpha.NetworkSpec{ + Provider: "multus", + Selectors: map[string]string{ + "server": `{"name": "macvlan", "interface": "net1"}`, + "broker": `{"name": "macvlan", "interface": "net2"}`, + }, + } + + objMeta := metav1.ObjectMeta{} + ApplyMultus(net, &objMeta) + + assert.Contains(t, objMeta.Annotations, "k8s.v1.cni.cncf.io/networks") + assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], `{"name": "macvlan", "interface": "net1"}`) + assert.Contains(t, objMeta.Annotations["k8s.v1.cni.cncf.io/networks"], `{"name": "macvlan", "interface": "net2"}`) +} + +func TestNetwork_ApplyMultusMixedError(t *testing.T) { + net := rookalpha.NetworkSpec{ + Provider: "multus", + Selectors: map[string]string{ + "server": `{"name": "macvlan", "interface": "net1"}`, + "broker": `macvlan@net2`, + }, + } + + objMeta := metav1.ObjectMeta{} + err := ApplyMultus(net, &objMeta) + + assert.Error(t, err) +}