diff --git a/test/extended/prometheus/prometheus.go b/test/extended/prometheus/prometheus.go index f26d92269998..db709bdc889b 100644 --- a/test/extended/prometheus/prometheus.go +++ b/test/extended/prometheus/prometheus.go @@ -425,14 +425,30 @@ var _ = g.Describe("[sig-instrumentation] Prometheus", func() { oc.SetupProject() ns := oc.Namespace() - execPod := exutil.CreateCentosExecPodOrFail(oc.AdminKubeClient(), ns, "execpod", nil) + cs, err := newDynClientSet() + o.Expect(err).NotTo(o.HaveOccurred()) + err = addNetwork(cs, "secondary", ns) + o.Expect(err).NotTo(o.HaveOccurred()) + + defer func() { + err := removeNetwork(cs, "secondary", ns) + o.Expect(err).NotTo(o.HaveOccurred()) + }() + + execPod := exutil.CreateCentosExecPodOrFail(oc.AdminKubeClient(), ns, "execpod", func(pod *v1.Pod) { + pod.Annotations = map[string]string{ + "k8s.v1.cni.cncf.io/networks": "secondary", + } + }) + defer func() { oc.AdminKubeClient().CoreV1().Pods(ns).Delete(context.Background(), execPod.Name, *metav1.NewDeleteOptions(1)) }() g.By("verifying named metrics keys") queries := map[string]bool{ - fmt.Sprintf(`pod_network_name_info{pod="%s",namespace="%s",interface="eth0"} == 0`, execPod.Name, execPod.Namespace): true, + fmt.Sprintf(`pod_network_name_info{pod="%s",namespace="%s",interface="eth0"} == 0`, execPod.Name, execPod.Namespace): true, + fmt.Sprintf(`pod_network_name_info{pod="%s",namespace="%s",network_name="secondary"} == 0`, execPod.Name, execPod.Namespace): true, } helper.RunQueries(queries, oc, ns, execPod.Name, url, bearerToken) }) diff --git a/test/extended/prometheus/secondary_network.go b/test/extended/prometheus/secondary_network.go new file mode 100644 index 000000000000..0fd4696b9193 --- /dev/null +++ b/test/extended/prometheus/secondary_network.go @@ -0,0 +1,170 @@ +package prometheus + +import ( + "fmt" + "time" + + "golang.org/x/net/context" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/dynamic" + + e2e "k8s.io/kubernetes/test/e2e/framework" +) + +type dynClientSet struct { + dc dynamic.Interface +} + +func (dcs dynClientSet) Networks() dynamic.ResourceInterface { + return dcs.dc.Resource(schema.GroupVersionResource{Group: "operator.openshift.io", Resource: "networks", Version: "v1"}) +} + +func (dcs dynClientSet) NetworkAttachmentDefinitions(namespace string) dynamic.ResourceInterface { + return dcs.dc.Resource(schema.GroupVersionResource{Group: "k8s.cni.cncf.io", Resource: "network-attachment-definitions", Version: "v1"}).Namespace(namespace) +} + +func newDynClientSet() (*dynClientSet, error) { + cfg, err := e2e.LoadConfig() + if err != nil { + return nil, err + } + + dc, err := dynamic.NewForConfig(cfg) + if err != nil { + return nil, err + } + + return &dynClientSet{ + dc: dc, + }, nil +} + +func addNetwork(client *dynClientSet, name, namespace string) error { + clusterNetwork, err := client.Networks().Get(context.Background(), "cluster", metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Failed to get cluster network %v", err) + } + + toUpdate := clusterNetwork.DeepCopy() + newSpec, ok := toUpdate.Object["spec"].(map[string]interface{}) + if !ok { + return fmt.Errorf("Failed to fetch spec for cluster network") + } + + nn, ok := newSpec["additionalNetworks"] + var newAdditionalNetworks []interface{} + if ok { + newAdditionalNetworks = nn.([]interface{}) + } else { + newAdditionalNetworks = make([]interface{}, 0) + } + + newAdditionalNetworks = append(newAdditionalNetworks, newMacVlan(name, namespace)) + newSpec["additionalNetworks"] = newAdditionalNetworks + + _, err = client.Networks().Update(context.Background(), toUpdate, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("Failed to update cluster network %v", err) + } + + err = waitForNetworkAttachmentDefinition(client, name, namespace) + if err != nil { + return fmt.Errorf("Failed waiting for network attachment definition %v", err) + } + return nil +} + +func removeNetwork(client *dynClientSet, name, namespace string) error { + clusterNetwork, err := client.Networks().Get(context.Background(), "cluster", metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("Failed to get cluster network %v", err) + } + + newClusterNetwork := clusterNetwork.DeepCopy() + + spec, ok := newClusterNetwork.Object["spec"].(map[string]interface{}) + if !ok { + return fmt.Errorf("Failed to fetch spec for cluster network") + } + + networks, ok := (spec["additionalNetworks"]).([]interface{}) + if !ok { + return fmt.Errorf("Failed to fetch additionalNetworks for cluster network %T", spec["additionalNetworks"]) + } + + for idx, n := range networks { + network, ok := n.(map[string]interface{}) + if !ok { + return fmt.Errorf("Failed to convert network to map") + } + if network["name"] == name && network["namespace"] == namespace { + networks = append(networks[:idx], networks[idx+1:]...) + break + } + } + + spec["additionalNetworks"] = networks + newClusterNetwork.Object["spec"] = spec + + _, err = client.Networks().Update(context.Background(), newClusterNetwork, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("Failed to update cluster network %v", err) + } + err = waitForNetworkAttachmentDefinitionDeleted(client, name, namespace) + if err != nil { + return fmt.Errorf("Failed to waiting for network attachment deletion %v", err) + } + + return nil +} + +func waitForNetworkAttachmentDefinition(client *dynClientSet, name, namespace string) error { + return wait.Poll(5*time.Second, 2*time.Minute, + func() (bool, error) { + _, err := client.NetworkAttachmentDefinitions(namespace).Get(context.Background(), name, metav1.GetOptions{}) + if err != nil && errors.IsNotFound(err) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil + }) +} + +func waitForNetworkAttachmentDefinitionDeleted(client *dynClientSet, name, namespace string) error { + return wait.Poll(5*time.Second, 2*time.Minute, + func() (bool, error) { + _, err := client.NetworkAttachmentDefinitions(namespace).Get(context.Background(), name, metav1.GetOptions{}) + if err != nil && errors.IsNotFound(err) { + return true, nil + } + if err != nil { + return false, err + } + return false, nil + }) +} + +func newMacVlan(name, namespace string) map[string]interface{} { + return map[string]interface{}{ + "name": name, + "namespace": namespace, + "type": "SimpleMacvlan", + "simpleMacvlanConfig": map[string]interface{}{ + "ipamConfig": map[string]interface{}{ + "type": "static", + "staticIPAMConfig": map[string]interface{}{ + "addresses": []map[string]interface{}{ + map[string]interface{}{ + "address": "10.1.1.0/24", + }, + }, + }, + }, + }, + } +}