diff --git a/Makefile b/Makefile index 58352ec376..befd649d75 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ manifests: controller-gen rbacs: controller-gen $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/advertisementoperator" rbac:roleName=liqo-advertisement output:rbac:stdout | sed -n '/rules/,$$p' > deployments/liqo/files/liqo-advertisement-rbac.yaml $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/route-operator" rbac:roleName=liqo-route output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-route-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-route-ClusterRole.yaml deployments/liqo/files/liqo-route-Role.yaml - $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnel-operator" rbac:roleName=liqo-gateway output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-gateway-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-gateway-ClusterRole.yaml deployments/liqo/files/liqo-gateway-Role.yaml + $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnel-operator" paths="./internal/liqonet/natmappingoperator" rbac:roleName=liqo-gateway output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-gateway-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-gateway-ClusterRole.yaml deployments/liqo/files/liqo-gateway-Role.yaml $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/liqonet/tunnelEndpointCreator" rbac:roleName=liqo-network-manager output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-network-manager-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-network-manager-ClusterRole.yaml deployments/liqo/files/liqo-network-manager-Role.yaml $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/crdReplicator" rbac:roleName=liqo-crd-replicator output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-crd-replicator-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-crd-replicator-ClusterRole.yaml deployments/liqo/files/liqo-crd-replicator-Role.yaml $(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./internal/peering-request-operator" rbac:roleName=liqo-peering-request output:rbac:stdout | awk -v RS="---\n" 'NR>1{f="./deployments/liqo/files/liqo-peering-request-" $$4 ".yaml";printf "%s",$$0 > f; close(f)}' && sed -i -n '/rules/,$$p' deployments/liqo/files/liqo-peering-request-ClusterRole.yaml deployments/liqo/files/liqo-peering-request-Role.yaml diff --git a/cmd/liqonet/main.go b/cmd/liqonet/main.go index 6aec1cd278..74a89af651 100644 --- a/cmd/liqonet/main.go +++ b/cmd/liqonet/main.go @@ -31,11 +31,13 @@ import ( clusterConfig "github.com/liqotech/liqo/apis/config/v1alpha1" netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + "github.com/liqotech/liqo/internal/liqonet/natmappingoperator" routeoperator "github.com/liqotech/liqo/internal/liqonet/route-operator" tunneloperator "github.com/liqotech/liqo/internal/liqonet/tunnel-operator" "github.com/liqotech/liqo/internal/liqonet/tunnelEndpointCreator" liqoconst "github.com/liqotech/liqo/pkg/consts" liqonetOperator "github.com/liqotech/liqo/pkg/liqonet" + liqonetns "github.com/liqotech/liqo/pkg/liqonet/netns" "github.com/liqotech/liqo/pkg/liqonet/overlay" liqorouting "github.com/liqotech/liqo/pkg/liqonet/routing" "github.com/liqotech/liqo/pkg/liqonet/utils" @@ -152,8 +154,23 @@ func main() { os.Exit(1) } eventRecorder := mgr.GetEventRecorderFor(liqoconst.LiqoGatewayOperatorName + "." + podIP.String()) + // This map is update by the tunnel operator after a successful tunnel creation + // and is consumed by the natmapping operator to check whether the tunnel is ready or not. + var readyClustersMutex sync.Mutex + readyClusters := make(map[string]struct{}) + // Create new network namespace for the gateway (gatewayNetns). + // If the namespace already exists it will be deleted and recreated. + // It is created here because both the tunnel-operator and the natmapping-operator + // need to know the namespace to configure. + gatewayNetns, err := liqonetns.CreateNetns(liqoconst.GatewayNetnsName) + if err != nil { + klog.Errorf("an error occurred while creating custom network namespace: %s", err.Error()) + os.Exit(1) + } + klog.Infof("created custom network namespace {%s}", liqoconst.GatewayNetnsName) tunnelController, err := tunneloperator.NewTunnelController(podIP.String(), - podNamespace, eventRecorder, clientset, mgr.GetClient()) + podNamespace, eventRecorder, clientset, mgr.GetClient(), &readyClustersMutex, + readyClusters, gatewayNetns) if err != nil { klog.Errorf("an error occurred while creating the tunnel controller: %v", err) _ = tunnelController.CleanUpConfiguration(liqoconst.GatewayNetnsName, liqoconst.HostVethName) @@ -164,6 +181,17 @@ func main() { klog.Errorf("unable to setup tunnel controller: %s", err) os.Exit(1) } + + nmo, err := natmappingoperator.NewController(mgr, &readyClustersMutex, readyClusters, gatewayNetns) + if err != nil { + klog.Errorf("an error occurred while creating the natmapping controller: %v", err) + os.Exit(1) + } + if err = nmo.SetupWithManager(mgr); err != nil { + klog.Errorf("unable to setup natmapping controller: %s", err) + os.Exit(1) + } + klog.Info("Starting manager as Tunnel-Operator") if err := mgr.Start(tunnelController.SetupSignalHandlerForTunnelOperator()); err != nil { klog.Errorf("unable to start tunnel controller: %s", err) os.Exit(1) diff --git a/deployments/liqo/files/liqo-gateway-ClusterRole.yaml b/deployments/liqo/files/liqo-gateway-ClusterRole.yaml index 8bb6fda068..5bc514c662 100644 --- a/deployments/liqo/files/liqo-gateway-ClusterRole.yaml +++ b/deployments/liqo/files/liqo-gateway-ClusterRole.yaml @@ -21,6 +21,18 @@ rules: - patch - update - watch +- apiGroups: + - net.liqo.io + resources: + - natmappings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - net.liqo.io resources: diff --git a/internal/liqonet/natmappingoperator/doc.go b/internal/liqonet/natmappingoperator/doc.go new file mode 100644 index 0000000000..f8ae5f0829 --- /dev/null +++ b/internal/liqonet/natmappingoperator/doc.go @@ -0,0 +1,3 @@ +// Package natmappingoperator is responsible of reconciling +// NatMapping resource and ensuring the proper set of NAT rules are inserted. +package natmappingoperator diff --git a/internal/liqonet/natmappingoperator/natmapping-operator.go b/internal/liqonet/natmappingoperator/natmapping-operator.go new file mode 100644 index 0000000000..7f97ad3ba3 --- /dev/null +++ b/internal/liqonet/natmappingoperator/natmapping-operator.go @@ -0,0 +1,97 @@ +package natmappingoperator + +import ( + "context" + "fmt" + "sync" + + "github.com/containernetworking/plugins/pkg/ns" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + "github.com/liqotech/liqo/pkg/liqonet/iptables" +) + +// NatMappingController reconciles a NatMapping object. +type NatMappingController struct { + client.Client + Scheme *runtime.Scheme + iptables.IPTHandler + readyClustersMutex *sync.Mutex + readyClusters map[string]struct{} + gatewayNetns ns.NetNS +} + +var result = ctrl.Result{ + Requeue: false, +} + +//+kubebuilder:rbac:groups=net.liqo.io,resources=natmappings,verbs=get;list;watch;create;update;patch;delete + +// Reconcile NatMapping resource. +func (npc *NatMappingController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + var nm netv1alpha1.NatMapping + + if err := npc.Get(ctx, req.NamespacedName, &nm); apierrors.IsNotFound(err) { + // Reconcile was triggered by a delete request + return result, client.IgnoreNotFound(err) + } else if err != nil { + // Unknown error + klog.Errorf("an error occurred while getting resource %s: %s", req.NamespacedName, err.Error()) + return result, err + } + // There's no need of a pre-delete logic since IPTables rules for cluster are removed by the + // tunnel-operator after the un-peer. + + // The following logic has to be executed in the custom network namespace, + // and not on the root namespace. Therefore it must be defined in a closure + // and then used as parameter of method Do of netNs + if err := npc.gatewayNetns.Do(func(netNamespace ns.NetNS) error { + // Is the remote cluster tunnel ready? If not, do nothing + npc.readyClustersMutex.Lock() + defer npc.readyClustersMutex.Unlock() + if _, ready := npc.readyClusters[nm.Spec.ClusterID]; !ready { + return fmt.Errorf("tunnel for cluster %s is not ready", nm.Spec.ClusterID) + } + + if err := npc.IPTHandler.EnsurePreroutingRulesPerNatMapping(&nm); err != nil { + klog.Errorf("unable to ensure prerouting rules: %s", err.Error()) + return err + } + return nil + }); err != nil { + return result, err + } + return result, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (npc *NatMappingController) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&netv1alpha1.NatMapping{}). + Complete(npc) +} + +// NewController returns a NAT mapping controller istance. +func NewController( + mgr ctrl.Manager, + readyClustersMutex *sync.Mutex, + readyClusters map[string]struct{}, + gatewayNetns ns.NetNS, +) (*NatMappingController, error) { + iptablesHandler, err := iptables.NewIPTHandler() + if err != nil { + return nil, err + } + return &NatMappingController{ + Client: mgr.GetClient(), + IPTHandler: iptablesHandler, + readyClustersMutex: readyClustersMutex, + readyClusters: readyClusters, + gatewayNetns: gatewayNetns, + }, nil +} diff --git a/internal/liqonet/natmappingoperator/natmapping_operator_test.go b/internal/liqonet/natmappingoperator/natmapping_operator_test.go new file mode 100644 index 0000000000..d086036e40 --- /dev/null +++ b/internal/liqonet/natmappingoperator/natmapping_operator_test.go @@ -0,0 +1,215 @@ +package natmappingoperator_test + +import ( + "context" + "fmt" + "strings" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/util/slice" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/liqotech/liqo/apis/net/v1alpha1" +) + +const ( + oldIP1 = "10.0.1.2" + oldIP2 = "10.0.1.5" + newIP1 = "10.0.2.4" + newIP2 = "10.0.3.7" + DNAT = "DNAT" + timeout = time.Second * 10 + interval = time.Millisecond * 250 +) + +var _ = Describe("NatmappingOperator", func() { + BeforeEach(func() { + // Clean resources + Eventually(func() bool { + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm1.ObjectMeta.Name, Namespace: "default"}, nm1) + if err != nil { + return false + } + nm1.Spec.ClusterMappings = make(v1alpha1.Mappings) + err = k8sClient.Update(context.Background(), nm1, &client.UpdateOptions{}) + return err == nil + }, timeout, interval).Should(BeTrue()) + Eventually(func() bool { + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm2.ObjectMeta.Name, Namespace: "default"}, nm2) + if err != nil { + return false + } + nm2.Spec.ClusterMappings = make(v1alpha1.Mappings) + err = k8sClient.Update(context.Background(), nm2, &client.UpdateOptions{}) + return err == nil + }, timeout, interval).Should(BeTrue()) + }) + Context("If the cluster is not ready", func() { + It("the controller should do nothing", func() { + // ClusterID2 is set as non ready in BeforeSuite, + // then even if natmapping resource of cluster + // contains some mappings, they should not result + // in real IPTables rules. + + Eventually(func() bool { + // Populate resource + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm2.ObjectMeta.Name, Namespace: "default"}, nm2) + if err != nil { + return false + } + nm2.Spec.ClusterMappings[oldIP1] = newIP1 + nm2.Spec.ClusterMappings[oldIP2] = newIP2 + err = k8sClient.Update(context.Background(), nm2, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() []string { + // Rules should not be present + rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID1)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID1), err.Error())) + } + return rules + }).Should(BeEmpty()) + }) + }) + Context("If the cluster is ready", func() { + It("the controller should insert the right rules", func() { + // ClusterID1 is set as ready in BeforeSuite + + Eventually(func() bool { + // Populate resource + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm1.ObjectMeta.Name, Namespace: "default"}, nm1) + if err != nil { + return false + } + nm1.Spec.ClusterMappings[oldIP1] = newIP1 + nm1.Spec.ClusterMappings[oldIP2] = newIP2 + err = k8sClient.Update(context.Background(), nm1, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() []string { + rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID1)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID1), err)) + } + return rules + }, timeout, interval).Should(ContainElements( + fmt.Sprintf("-d %s -j %s --to-destination %s", newIP1, DNAT, oldIP1), + fmt.Sprintf("-d %s -j %s --to-destination %s", newIP2, DNAT, oldIP2), + )) + }) + }) + Context("If natmapping resource is updated with deletion and insertion of mappings", func() { + It("the controller should update IPTables rules", func() { + Eventually(func() bool { + // Insert mapping for oldIP1 + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm1.ObjectMeta.Name, Namespace: "default"}, nm1) + if err != nil { + return false + } + nm1.Spec.ClusterMappings[oldIP1] = newIP1 + err = k8sClient.Update(context.Background(), nm1, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() []string { + rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID1)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID1), err)) + } + return rules + }, timeout, interval).Should(ContainElements( + fmt.Sprintf("-d %s -j %s --to-destination %s", newIP1, DNAT, oldIP1), + )) + + Eventually(func() bool { + // Insert mapping for oldIP1 + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm1.ObjectMeta.Name, Namespace: "default"}, nm1) + if err != nil { + return false + } + // Delete mapping for oldIP1 + delete(nm1.Spec.ClusterMappings, oldIP1) + // Insert mapping for oldIP2 + nm1.Spec.ClusterMappings[oldIP2] = newIP2 + err = k8sClient.Update(context.Background(), nm1, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() bool { + rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID1)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID1), err)) + } + // Should contain the rule for oldIP1 but it should not contain the rule for oldIP2 + if slice.ContainsString(rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP2, DNAT, oldIP2), nil) && + !slice.ContainsString(rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP1, DNAT, oldIP1), nil) { + return true + } + return false + }, timeout, interval).Should(BeTrue()) + }) + }) + + Context("If mappings for more clusters are active", func() { + It("the controller should update IPTables rules independently", func() { + // Set cluster2 as ready + readyClustersMutex.Lock() + readyClusters[clusterID2] = struct{}{} + readyClustersMutex.Unlock() + Eventually(func() bool { + // Insert mapping for oldIP1 in cluster1 + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm1.ObjectMeta.Name, Namespace: "default"}, nm1) + if err != nil { + return false + } + nm1.Spec.ClusterMappings[oldIP1] = newIP1 + err = k8sClient.Update(context.Background(), nm1, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() bool { + // Insert mapping for oldIP2 in cluster2 + err := k8sClient.Get(context.Background(), types.NamespacedName{Name: nm2.ObjectMeta.Name, Namespace: "default"}, nm2) + if err != nil { + return false + } + nm2.Spec.ClusterMappings[oldIP2] = newIP2 + err = k8sClient.Update(context.Background(), nm2, &client.UpdateOptions{}) + return err == nil + }).Should(BeTrue()) + + Eventually(func() bool { + cluster1Rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID1)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID1), err)) + } + cluster2Rules, err := ipt.ListRulesInChain(getClusterPreRoutingMappingChain(clusterID2)) + if err != nil { + Fail(fmt.Sprintf("failed to list rules in chain %s: %s", getClusterPreRoutingMappingChain(clusterID2), err)) + } + // Cluster1 rules should contain the rule for oldIP1 and not contain the rule for oldIP2 + if !slice.ContainsString(cluster1Rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP1, DNAT, oldIP1), nil) || + slice.ContainsString(cluster1Rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP2, DNAT, oldIP2), nil) { + return false + } + // Cluster2 rules should contain the rule for oldIP2 and not contain the rule for oldIP1 + if !slice.ContainsString(cluster2Rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP2, DNAT, oldIP2), nil) || + slice.ContainsString(cluster2Rules, fmt.Sprintf("-d %s -j %s --to-destination %s", newIP1, DNAT, oldIP1), nil) { + return false + } + return true + }, timeout, interval).Should(BeTrue()) + }) + }) +}) + +func getClusterPreRoutingMappingChain(clusterID string) string { + const liqonetPreRoutingMappingClusterChainPrefix = "LIQO-PRRT-MAP-CLS-" + return fmt.Sprintf("%s%s", liqonetPreRoutingMappingClusterChainPrefix, strings.Split(clusterID, "-")[0]) +} diff --git a/internal/liqonet/natmappingoperator/natmappingoperator_suite_test.go b/internal/liqonet/natmappingoperator/natmappingoperator_suite_test.go new file mode 100644 index 0000000000..a0b64683a9 --- /dev/null +++ b/internal/liqonet/natmappingoperator/natmappingoperator_suite_test.go @@ -0,0 +1,144 @@ +package natmappingoperator_test + +import ( + "context" + "path/filepath" + "sync" + "testing" + + "github.com/containernetworking/plugins/pkg/ns" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + controllerruntime "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + + netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" + "github.com/liqotech/liqo/internal/liqonet/natmappingoperator" + "github.com/liqotech/liqo/pkg/liqonet/iptables" + testutils "github.com/liqotech/liqo/pkg/utils/testUtils" +) + +const ( + clusterID1 = "cluster1" + clusterID2 = "cluster2" +) + +var ( + envTest *envtest.Environment + ipt iptables.IPTHandler + k8sClient client.Client + controller *natmappingoperator.NatMappingController + readyClustersMutex sync.Mutex + readyClusters = map[string]struct{}{ + clusterID1: {}, + } + tep1 *netv1alpha1.TunnelEndpoint + tep2 *netv1alpha1.TunnelEndpoint + nm1 *netv1alpha1.NatMapping + nm2 *netv1alpha1.NatMapping +) + +func TestNatmappingoperator(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Natmappingoperator Suite") +} + +var _ = BeforeSuite(func() { + var err error + + // Forge TEP resources for clusters + tep1 = testutils.ForgeTEPResource(clusterID1) + tep2 = testutils.ForgeTEPResource(clusterID2) + + // Forge NM resources for clusters + nm1 = testutils.ForgeNMResource(clusterID1, make(netv1alpha1.Mappings)) + nm2 = testutils.ForgeNMResource(clusterID2, make(netv1alpha1.Mappings)) + + // Config IPTables for remote clusters + err = initIPTables() + Expect(err).To(BeNil()) + + err = netv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).To(BeNil()) + //+kubebuilder:scaffold:scheme + envTest = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "deployments", "liqo", "crds")}, + } + config, err := envTest.Start() + Expect(err).To(BeNil()) + mgr, err := controllerruntime.NewManager(config, controllerruntime.Options{ + Scheme: scheme.Scheme, + MetricsBindAddress: "0", + }) + + // Since tests are carried out in a container, + // it is not necessary to create a custom network namespace + netns, err := ns.GetCurrentNS() + Expect(err).To(BeNil()) + controller, err = natmappingoperator.NewController(mgr, &readyClustersMutex, readyClusters, netns) + Expect(err).To(BeNil()) + err = controller.SetupWithManager(mgr) + Expect(err).To(BeNil()) + go func() { + if err = mgr.Start(controllerruntime.SetupSignalHandler()); err != nil { + panic(err) + } + }() + k8sClient = mgr.GetClient() + // Create resources + err = k8sClient.Create(context.Background(), nm1, &client.CreateOptions{}) + Expect(err).To(BeNil()) + err = k8sClient.Create(context.Background(), nm2, &client.CreateOptions{}) + Expect(err).To(BeNil()) +}) + +var _ = AfterSuite(func() { + err := envTest.Stop() + Expect(err).To(BeNil()) + err = terminateIPTables() + Expect(err).To(BeNil()) +}) + +func terminateIPTables() error { + var err error + err = ipt.RemoveIPTablesConfigurationPerCluster(tep1) + if err != nil { + return err + } + err = ipt.RemoveIPTablesConfigurationPerCluster(tep2) + if err != nil { + return err + } + err = ipt.Terminate() + if err != nil { + return err + } + return nil +} + +func initIPTables() error { + var err error + // Allocate new IPTable handler + ipt, err = iptables.NewIPTHandler() + if err != nil { + return err + } + if err := ipt.Init(); err != nil { + return err + } + if err := ipt.EnsureChainsPerCluster(clusterID1); err != nil { + return err + } + if err := ipt.EnsureChainsPerCluster(clusterID2); err != nil { + return err + } + if err := ipt.EnsureChainRulesPerCluster(tep1); err != nil { + return err + } + if err := ipt.EnsureChainRulesPerCluster(tep2); err != nil { + return err + } + return nil +} diff --git a/internal/liqonet/tunnel-operator/tunnel-operator.go b/internal/liqonet/tunnel-operator/tunnel-operator.go index 8043a98ec6..a822d46553 100644 --- a/internal/liqonet/tunnel-operator/tunnel-operator.go +++ b/internal/liqonet/tunnel-operator/tunnel-operator.go @@ -22,6 +22,7 @@ import ( "os/signal" "reflect" "strings" + "sync" "github.com/containernetworking/plugins/pkg/ns" "github.com/vishvananda/netlink" @@ -57,14 +58,16 @@ type TunnelController struct { tunnel.Driver liqorouting.Routing iptables.IPTHandler - k8sClient k8s.Interface - drivers map[string]tunnel.Driver - namespace string - podIP string - hostNetns ns.NetNS - gatewayNetns ns.NetNS - hostVeth netlink.Link - gatewayVeth netlink.Link + k8sClient k8s.Interface + drivers map[string]tunnel.Driver + namespace string + podIP string + hostNetns ns.NetNS + gatewayNetns ns.NetNS + hostVeth netlink.Link + gatewayVeth netlink.Link + readyClustersMutex *sync.Mutex + readyClusters map[string]struct{} } // cluster-role @@ -79,13 +82,17 @@ type TunnelController struct { // NewTunnelController instantiates and initializes the tunnel controller. func NewTunnelController(podIP, namespace string, er record.EventRecorder, - k8sClient k8s.Interface, cl client.Client) (*TunnelController, error) { + k8sClient k8s.Interface, cl client.Client, readyClustersMutex *sync.Mutex, + readyClusters map[string]struct{}, gatewayNetns ns.NetNS) (*TunnelController, error) { tc := &TunnelController{ - Client: cl, - EventRecorder: er, - k8sClient: k8sClient, - podIP: podIP, - namespace: namespace, + Client: cl, + EventRecorder: er, + k8sClient: k8sClient, + podIP: podIP, + namespace: namespace, + readyClustersMutex: readyClustersMutex, + readyClusters: readyClusters, + gatewayNetns: gatewayNetns, } err := tc.SetUpTunnelDrivers() @@ -155,6 +162,10 @@ func (tc *TunnelController) Reconcile(ctx context.Context, req ctrl.Request) (ct if err = tc.EnsureIPTablesRulesPerCluster(tep); err != nil { return err } + // Set cluster tunnel as ready + tc.readyClustersMutex.Lock() + defer tc.readyClustersMutex.Unlock() + tc.readyClusters[tep.Spec.ClusterID] = struct{}{} added, err := tc.EnsureRoutesPerCluster(tep) if err != nil { klog.Errorf("%s -> unable to configure route '%s': %s", clusterID, remotePodCIDR, err) @@ -464,13 +475,6 @@ func (tc *TunnelController) setUpGWNetns(netnsName, hostVethName, gatewayVethNam if err != nil { return err } - // Create new network namespace for the gateway (gatewayNetns). - // If the namespace already exists it will be deleted and recreated. - tc.gatewayNetns, err = liqonetns.CreateNetns(netnsName) - if err != nil { - return err - } - klog.Infof("created custom network namespace {%s}", netnsName) // Create veth pair to connect the two namespaces. err = liqonetns.CreateVethPair(hostVethName, gatewayVethName, tc.hostNetns, tc.gatewayNetns, vethMtu) if err != nil { diff --git a/internal/liqonet/tunnel-operator/tunnel_operator_suite_test.go b/internal/liqonet/tunnel-operator/tunnel_operator_suite_test.go index eb7f86292b..1ad77dd853 100644 --- a/internal/liqonet/tunnel-operator/tunnel_operator_suite_test.go +++ b/internal/liqonet/tunnel-operator/tunnel_operator_suite_test.go @@ -5,6 +5,9 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + "github.com/liqotech/liqo/pkg/consts" + "github.com/liqotech/liqo/pkg/liqonet/netns" ) var ( @@ -15,3 +18,11 @@ func TestTunnelOperator(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "TunnelOperator Suite") } + +var _ = BeforeSuite(func() { + // Create custom network namespace and set related field in + // tunnelcontroller struct + gatewayNetns, err := netns.CreateNetns(consts.GatewayNetnsName) + Expect(err).To(BeNil()) + tc.gatewayNetns = gatewayNetns +}) diff --git a/internal/liqonet/tunnel-operator/tunnel_operator_test.go b/internal/liqonet/tunnel-operator/tunnel_operator_test.go index 76a1bec46a..03189272cc 100644 --- a/internal/liqonet/tunnel-operator/tunnel_operator_test.go +++ b/internal/liqonet/tunnel-operator/tunnel_operator_test.go @@ -9,12 +9,11 @@ import ( "github.com/vishvananda/netlink" liqoconst "github.com/liqotech/liqo/pkg/consts" - "github.com/liqotech/liqo/pkg/liqonet/netns" ) var _ = Describe("TunnelOperator", func() { Describe("setup gateway namespace", func() { - Context("creating a new gateway namespace", func() { + Context("configuring the new gateway namespace", func() { JustAfterEach(func() { link, err := netlink.LinkByName(liqoconst.HostVethName) if err != nil { @@ -26,10 +25,8 @@ var _ = Describe("TunnelOperator", func() { if link != nil { Expect(netlink.LinkDel(link)).ShouldNot(HaveOccurred()) } - Expect(netns.DeleteNetns(liqoconst.GatewayNetnsName)).ShouldNot(HaveOccurred()) }) It("should return nil", func() { - tc := &TunnelController{} err := tc.setUpGWNetns(liqoconst.GatewayNetnsName, liqoconst.HostVethName, liqoconst.GatewayVethName, "169.254.1.134/32", 1420) Expect(err).ShouldNot(HaveOccurred()) @@ -54,8 +51,6 @@ var _ = Describe("TunnelOperator", func() { return nil }) Expect(tc.hostNetns.Close()).ShouldNot(HaveOccurred()) - Expect(tc.gatewayNetns.Close()).ShouldNot(HaveOccurred()) - }) It("incorrect name for veth interface, should return error", func() { @@ -65,7 +60,6 @@ var _ = Describe("TunnelOperator", func() { }) It("incorrect ip address for veth interface, should return error", func() { - tc := &TunnelController{} err := tc.setUpGWNetns(liqoconst.GatewayNetnsName, liqoconst.HostVethName, liqoconst.GatewayVethName, "169.254.1.1.34/24", 1420) Expect(err).Should(HaveOccurred()) Expect(err).Should(MatchError(&net.ParseError{Text: "169.254.1.1.34/24", Type: "CIDR address"})) diff --git a/pkg/liqonet/errors/errors.go b/pkg/liqonet/errors/errors.go index 516238d549..9bbad96827 100644 --- a/pkg/liqonet/errors/errors.go +++ b/pkg/liqonet/errors/errors.go @@ -15,7 +15,7 @@ const ( // ValidIP used as reason of failure in WrongParameter error. ValidIP = "a valid IP address" // NotNil used as reason of failure in WrongParameter error. - NotNil = "have to be not nil" + NotNil = "not nil" // ValidCIDR used as reason of failure in WrongParameter error. ValidCIDR = "a valid network CIDR" // StringNotEmpty used as reason of failure in WrongParameter error. diff --git a/pkg/liqonet/iptables/coverage.txt b/pkg/liqonet/iptables/coverage.txt deleted file mode 100644 index c64302d271..0000000000 --- a/pkg/liqonet/iptables/coverage.txt +++ /dev/null @@ -1,225 +0,0 @@ -mode: atomic -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:69.42,71.16 2 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:74.2,76.8 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:71.16,73.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:85.34,90.55 2 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:95.2,98.53 2 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:101.2,101.12 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:90.55,92.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:98.53,100.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:105.70,106.31 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:111.2,111.12 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:106.31,107.91 1 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:107.91,109.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:115.73,116.33 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:121.2,121.12 1 40 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:116.33,117.66 1 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:117.66,119.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:126.44,133.2 1 78 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:137.39,139.44 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:143.2,143.45 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:146.2,147.12 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:139.44,141.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:143.45,145.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:151.45,154.37 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:159.2,159.12 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:154.37,155.74 1 152 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:155.74,157.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:163.97,165.16 2 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:168.2,169.15 2 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:197.2,197.88 1 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:200.2,200.12 1 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:165.16,167.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:170.16,182.4 3 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:183.19,194.4 3 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:197.88,199.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:204.46,209.74 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:214.2,214.77 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:217.2,217.12 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:209.74,211.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:214.77,216.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:220.97,221.42 1 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:235.2,235.12 1 76 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:221.42,223.47 1 156 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:227.3,227.56 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:230.3,230.57 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:233.3,233.77 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:223.47,224.12 1 156 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:227.56,229.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:230.57,232.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:240.87,242.16 2 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:245.2,245.42 1 8 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:260.2,260.12 1 8 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:242.16,244.3 1 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:245.42,253.17 2 32 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:256.3,256.79 1 32 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:253.17,255.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:256.79,258.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:263.86,267.16 3 32 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:273.2,276.29 2 32 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:286.2,286.32 1 32 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:267.16,270.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:276.29,277.46 1 10 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:277.46,278.45 1 30 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:282.4,283.9 2 10 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:278.45,279.13 1 20 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:289.53,298.2 2 105 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:302.68,303.21 1 36 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:310.2,311.31 2 35 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:316.2,316.12 1 35 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:303.21,308.3 1 1 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:311.31,312.91 1 175 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:312.91,314.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:321.45,324.59 1 1701 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:327.2,329.64 1 1411 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:333.2,333.15 1 1033 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:339.2,339.11 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:324.59,326.3 1 290 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:329.64,331.3 1 378 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:334.75,335.21 1 514 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:336.90,337.18 1 519 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:345.98,348.16 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:352.2,353.16 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:356.2,357.12 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:348.16,350.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:353.16,355.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:362.87,364.16 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:367.2,367.46 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:373.2,373.12 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:364.16,366.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:367.46,369.17 2 152 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:369.17,371.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:376.81,379.16 3 304 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:382.2,382.29 1 304 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:392.2,392.12 1 304 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:379.16,381.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:382.29,383.73 1 338 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:387.3,387.61 1 177 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:390.3,390.75 1 177 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:383.73,384.12 1 161 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:387.61,389.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:396.68,399.16 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:403.2,404.16 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:408.2,411.31 2 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:439.2,439.12 1 38 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:399.16,401.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:404.16,406.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:411.31,412.98 1 190 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:426.3,426.104 1 88 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:412.98,414.60 1 102 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:417.4,417.60 1 102 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:420.4,420.61 1 102 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:423.4,424.12 2 102 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:414.60,415.13 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:417.60,419.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:420.61,422.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:426.104,427.63 1 68 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:430.4,430.63 1 68 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:433.4,433.64 1 68 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:436.4,436.79 1 68 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:427.63,428.13 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:430.63,432.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:433.64,435.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:443.83,446.16 3 11 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:449.2,449.76 1 6 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:446.16,448.3 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:454.99,457.16 3 9 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:460.2,460.75 1 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:457.16,459.3 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:465.90,468.16 3 6 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:471.2,471.82 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:468.16,470.3 1 1 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:474.98,476.44 1 9 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:479.2,483.53 4 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:489.2,492.19 2 3 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:476.44,478.3 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:483.53,487.3 1 1 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:495.89,497.29 1 6 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:504.2,506.52 2 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:511.2,511.19 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:497.29,502.3 1 1 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:506.52,510.3 1 9 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:515.95,517.34 2 158 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:522.2,522.8 1 158 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:517.34,518.31 1 867 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:518.31,520.4 1 14 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:526.70,528.16 2 407 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:531.2,533.37 3 407 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:540.2,540.19 1 407 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:528.16,530.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:533.37,534.27 1 646 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:534.27,538.4 3 404 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:543.82,546.16 2 335 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:550.2,550.35 1 335 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:556.2,557.16 2 174 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:560.2,561.12 2 174 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:546.16,548.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:550.35,551.24 1 1921 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:551.24,553.4 1 161 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:557.16,559.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:564.85,568.16 3 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:572.2,573.45 2 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:579.2,579.24 1 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:589.2,589.25 1 160 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:602.2,602.25 1 148 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:609.2,609.12 1 148 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:568.16,570.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:573.45,574.62 1 172 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:574.62,576.4 1 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:579.24,580.39 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:585.3,585.63 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:580.39,581.61 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:581.61,583.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:585.63,587.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:589.25,591.66 1 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:594.3,594.60 1 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:597.3,597.63 1 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:600.3,600.13 1 12 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:591.66,593.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:594.60,596.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:597.63,599.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:602.25,604.63 1 148 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:607.3,607.79 1 148 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:604.63,606.4 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:613.117,615.45 2 47 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:632.2,633.16 2 47 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:636.2,636.12 1 47 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:615.45,619.36 2 17 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:624.3,624.15 1 17 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:619.36,620.66 1 25 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:620.66,622.5 1 2 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:624.15,625.90 1 15 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:629.4,629.95 1 15 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:625.90,628.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:633.16,635.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:640.85,642.16 2 15 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:645.2,645.70 1 15 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:642.16,644.3 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:648.93,649.29 1 47 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:662.2,662.12 1 47 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:649.29,651.17 2 61 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:655.3,655.14 1 61 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:651.17,654.4 2 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:655.14,656.68 1 59 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:659.4,659.81 1 59 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:656.68,658.5 1 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:665.82,666.44 1 11 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:669.2,672.53 4 6 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:687.2,688.16 2 2 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:693.2,695.8 1 2 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:666.44,668.3 1 5 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:672.53,676.17 2 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:681.3,684.9 1 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:676.17,680.4 2 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:688.16,692.3 2 0 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:701.97,702.44 1 50 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:705.2,726.53 13 46 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:733.2,733.24 1 46 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:702.44,704.3 1 4 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:726.53,732.3 1 41 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:736.57,738.2 1 155 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:740.58,742.2 1 165 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:744.54,746.2 1 153 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:748.52,750.2 1 153 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:752.64,754.2 1 163 -github.com/liqotech/liqo/pkg/liqonet/iptables/iptables.go:759.40,766.2 1 82 diff --git a/pkg/liqonet/iptables/iptables_test.go b/pkg/liqonet/iptables/iptables_test.go index af7cceca2f..3ee0f692ba 100644 --- a/pkg/liqonet/iptables/iptables_test.go +++ b/pkg/liqonet/iptables/iptables_test.go @@ -15,17 +15,17 @@ import ( "github.com/liqotech/liqo/pkg/consts" "github.com/liqotech/liqo/pkg/liqonet/errors" "github.com/liqotech/liqo/pkg/liqonet/utils" + testutils "github.com/liqotech/liqo/pkg/utils/testUtils" ) const ( - clusterID1 = "cluster1" - invalidValue = "an invalid value" - remoteNATPodCIDRValue1 = "10.60.0.0/24" - remoteNATPodCIDRValue2 = "10.70.0.0/24" - oldIP1 = "10.0.0.2" - oldIP2 = "12.0.0.4" - newIP1 = "10.0.3.2" - newIP2 = "10.0.5.2" + clusterID1 = "cluster1" + invalidValue = "an invalid value" + remoteNATPodCIDRValue = "10.70.0.0/24" + oldIP1 = "10.0.0.2" + oldIP2 = "12.0.0.4" + newIP1 = "10.0.3.2" + newIP2 = "10.0.5.2" ) var ( @@ -46,8 +46,8 @@ var _ = Describe("iptables", func() { Expect(err).To(BeNil()) ipt, err = New() Expect(err).To(BeNil()) - tep = forgeValidTEPResource() - nm = forgeValidNMResource() + tep = testutils.ForgeTEPResource(clusterID1) + nm = testutils.ForgeNMResource(clusterID1, natMappings) }) Describe("Init", func() { Context("Call func", func() { @@ -199,7 +199,7 @@ var _ = Describe("iptables", func() { tep.Status.RemoteNATPodCIDR = invalidValue err := h.EnsureChainRulesPerCluster(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.RemoteNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) @@ -210,7 +210,7 @@ var _ = Describe("iptables", func() { tep.Spec.PodCIDR = invalidValue err := h.EnsureChainRulesPerCluster(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.PodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() // Otherwise RemoveIPTablesConfigurationPerCluster would fail in AfterEach + tep = testutils.ForgeTEPResource(clusterID1) // Otherwise RemoveIPTablesConfigurationPerCluster would fail in AfterEach }) }) @@ -220,7 +220,7 @@ var _ = Describe("iptables", func() { tep.Status.LocalNATPodCIDR = invalidValue err := h.EnsureChainRulesPerCluster(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) @@ -232,7 +232,7 @@ var _ = Describe("iptables", func() { Expect(err).To(BeNil()) err = h.EnsureChainRulesPerCluster(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) @@ -248,7 +248,7 @@ var _ = Describe("iptables", func() { outdatedRule := postRoutingRules[0] // Modify resource - tep.Status.RemoteNATPodCIDR = remoteNATPodCIDRValue2 + tep.Status.RemoteNATPodCIDR = remoteNATPodCIDRValue // Second call err = h.EnsureChainRulesPerCluster(tep) @@ -276,7 +276,7 @@ var _ = Describe("iptables", func() { outdatedRule := postRoutingRules[0] // Modify resource - tep.Status.RemoteNATPodCIDR = remoteNATPodCIDRValue2 + tep.Status.RemoteNATPodCIDR = remoteNATPodCIDRValue // Second call err = h.EnsureChainRulesPerCluster(tep) @@ -297,7 +297,7 @@ var _ = Describe("iptables", func() { BeforeEach(func() { err := h.Init() Expect(err).To(BeNil()) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) AfterEach(func() { err := h.RemoveIPTablesConfigurationPerCluster(tep) @@ -525,8 +525,6 @@ var _ = Describe("iptables", func() { Context("If cluster has an iptables configuration", func() { It("should delete chains and rules per cluster", func() { // Init configuration - tep := forgeValidTEPResource() - err := h.EnsureChainsPerCluster(tep.Spec.ClusterID) Expect(err).To(BeNil()) @@ -607,7 +605,7 @@ var _ = Describe("iptables", func() { tep.Spec.ClusterID = "" err := h.EnsurePostroutingRules(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.ClusterIDLabelName, errors.StringNotEmpty))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("If tep has an invalid LocalPodCIDR", func() { @@ -615,7 +613,7 @@ var _ = Describe("iptables", func() { tep.Status.LocalPodCIDR = invalidValue err := h.EnsurePostroutingRules(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("If tep has an invalid LocalNATPodCIDR", func() { @@ -623,7 +621,7 @@ var _ = Describe("iptables", func() { tep.Status.LocalNATPodCIDR = invalidValue err := h.EnsurePostroutingRules(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context(fmt.Sprintf("If tep has Status.RemoteNATPodCIDR = %s and an invalid Spec.PodCIDR", @@ -633,7 +631,7 @@ var _ = Describe("iptables", func() { tep.Spec.PodCIDR = invalidValue err := h.EnsurePostroutingRules(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.PodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context(fmt.Sprintf("If tep has an invalid Status.RemoteNATPodCIDR != %s", @@ -642,7 +640,7 @@ var _ = Describe("iptables", func() { tep.Status.RemoteNATPodCIDR = invalidValue err := h.EnsurePostroutingRules(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.RemoteNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("Call with different parameters", func() { @@ -739,7 +737,7 @@ var _ = Describe("iptables", func() { tep.Spec.ClusterID = "" err := h.EnsurePreroutingRulesPerTunnelEndpoint(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.ClusterIDLabelName, errors.StringNotEmpty))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("If tep has an invalid LocalPodCIDR", func() { @@ -747,7 +745,7 @@ var _ = Describe("iptables", func() { tep.Status.LocalPodCIDR = invalidValue err := h.EnsurePreroutingRulesPerTunnelEndpoint(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("If tep has an invalid LocalNATPodCIDR", func() { @@ -755,7 +753,7 @@ var _ = Describe("iptables", func() { tep.Status.LocalNATPodCIDR = invalidValue err := h.EnsurePreroutingRulesPerTunnelEndpoint(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.LocalNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context(fmt.Sprintf("If tep has Status.RemoteNATPodCIDR = %s and an invalid Spec.PodCIDR", @@ -765,7 +763,7 @@ var _ = Describe("iptables", func() { tep.Spec.PodCIDR = invalidValue err := h.EnsurePreroutingRulesPerTunnelEndpoint(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.PodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context(fmt.Sprintf("If tep has an invalid Status.RemoteNATPodCIDR != %s", @@ -774,7 +772,7 @@ var _ = Describe("iptables", func() { tep.Status.RemoteNATPodCIDR = invalidValue err := h.EnsurePreroutingRulesPerTunnelEndpoint(tep) Expect(err).To(MatchError(fmt.Sprintf("invalid TunnelEndpoint resource: %s must be %s", consts.RemoteNATPodCIDR, errors.ValidCIDR))) - tep = forgeValidTEPResource() + tep = testutils.ForgeTEPResource(clusterID1) }) }) Context("Call with different parameters", func() { @@ -846,7 +844,7 @@ var _ = Describe("iptables", func() { nm.Spec.ClusterID = "" err := h.EnsurePreroutingRulesPerNatMapping(nm) Expect(err).To(MatchError(fmt.Sprintf("%s must be %s", consts.ClusterIDLabelName, errors.StringNotEmpty))) - nm = forgeValidNMResource() + nm = testutils.ForgeNMResource(clusterID1, natMappings) }) }) Context("Call with same mappings", func() { @@ -919,36 +917,6 @@ var _ = Describe("iptables", func() { }) }) -func forgeValidTEPResource() *v1alpha1.TunnelEndpoint { - return &v1alpha1.TunnelEndpoint{ - Spec: v1alpha1.TunnelEndpointSpec{ - ClusterID: clusterID1, - PodCIDR: "10.0.0.0/24", - ExternalCIDR: "10.0.1.0/24", - EndpointIP: "172.10.0.2", - BackendType: "backendType", - BackendConfig: make(map[string]string), - }, - Status: v1alpha1.TunnelEndpointStatus{ - LocalPodCIDR: "192.168.0.0/24", - LocalNATPodCIDR: "192.168.1.0/24", - RemoteNATPodCIDR: remoteNATPodCIDRValue1, - LocalExternalCIDR: "192.168.3.0/24", - LocalNATExternalCIDR: "192.168.4.0/24", - RemoteNATExternalCIDR: "192.168.5.0/24", - }, - } -} - -func forgeValidNMResource() *v1alpha1.NatMapping { - return &v1alpha1.NatMapping{ - Spec: v1alpha1.NatMappingSpec{ - ClusterID: clusterID1, - ClusterMappings: natMappings, - }, - } -} - func mustGetFirstIP(network string) string { firstIP, err := utils.GetFirstIP(network) if err != nil { diff --git a/pkg/utils/testUtils/resources.go b/pkg/utils/testUtils/resources.go new file mode 100644 index 0000000000..0fd432edb5 --- /dev/null +++ b/pkg/utils/testUtils/resources.go @@ -0,0 +1,44 @@ +package testutils + +import ( + "fmt" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/liqotech/liqo/apis/net/v1alpha1" +) + +// ForgeTEPResource func returns a TunnelEndpoint resource. +func ForgeTEPResource(clusterID string) *v1alpha1.TunnelEndpoint { + return &v1alpha1.TunnelEndpoint{ + Spec: v1alpha1.TunnelEndpointSpec{ + ClusterID: clusterID, + PodCIDR: "10.0.0.0/24", + ExternalCIDR: "10.0.1.0/24", + EndpointIP: "172.10.0.2", + BackendType: "backendType", + BackendConfig: make(map[string]string), + }, + Status: v1alpha1.TunnelEndpointStatus{ + LocalPodCIDR: "192.168.0.0/24", + LocalNATPodCIDR: "192.168.1.0/24", + RemoteNATPodCIDR: "10.60.0.0/24", + LocalExternalCIDR: "192.168.3.0/24", + LocalNATExternalCIDR: "192.168.4.0/24", + RemoteNATExternalCIDR: "192.168.5.0/24", + }, + } +} + +// ForgeNMResource function returns a NatMapping resource. +func ForgeNMResource(clusterID string, natMappings v1alpha1.Mappings) *v1alpha1.NatMapping { + return &v1alpha1.NatMapping{ + ObjectMeta: v1.ObjectMeta{ + Name: fmt.Sprintf("nm-%s", clusterID), + }, + Spec: v1alpha1.NatMappingSpec{ + ClusterID: clusterID, + ClusterMappings: natMappings, + }, + } +}