Adds policy and test for network isolation. This will not work on docker-desktop clusters.

This commit is contained in:
benbierens 2023-05-04 14:55:39 +02:00
parent 533bf32577
commit eae138f7fd
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
4 changed files with 100 additions and 24 deletions

View File

@ -128,9 +128,16 @@ namespace DistTestCore
return Get().CodexStarter.BringOnline((CodexSetup)codexSetup); return Get().CodexStarter.BringOnline((CodexSetup)codexSetup);
} }
protected BaseLog Log protected void Log(string msg)
{ {
get { return Get().Log; } TestContext.Progress.WriteLine(msg);
Get().Log.Log(msg);
}
protected void Debug(string msg)
{
TestContext.Progress.WriteLine(msg);
Get().Log.Debug(msg);
} }
private TestLifecycle Get() private TestLifecycle Get()

View File

@ -92,6 +92,10 @@ namespace DistTestCore
public ICodexSetup BringOffline() public ICodexSetup BringOffline()
{ {
if (Group.Count() > 1) throw new InvalidOperationException("Codex-nodes that are part of a group cannot be " +
"individually shut down. Use 'BringOffline()' on the group object to stop the group. This method is only " +
"available for codex-nodes in groups of 1.");
return Group.BringOffline(); return Group.BringOffline();
} }

View File

@ -22,7 +22,7 @@ namespace KubernetesWorkflow
client = new K8sClient(cluster.GetK8sClientConfig()); client = new K8sClient(cluster.GetK8sClientConfig());
K8sTestNamespace = cluster.Configuration.K8sNamespacePrefix + testNamespace; K8sTestNamespace = cluster.Configuration.K8sNamespacePrefix + testNamespace;
log.Debug($"'{K8sTestNamespace}'"); log.Debug($"Test namespace: '{K8sTestNamespace}'");
} }
public void Dispose() public void Dispose()
@ -121,6 +121,8 @@ namespace KubernetesWorkflow
}; };
client.Run(c => c.CreateNamespace(namespaceSpec)); client.Run(c => c.CreateNamespace(namespaceSpec));
WaitUntilNamespaceCreated(); WaitUntilNamespaceCreated();
CreatePolicy();
} }
private bool IsTestNamespaceOnline() private bool IsTestNamespaceOnline()
@ -133,6 +135,67 @@ namespace KubernetesWorkflow
return client.Run(c => c.ListNamespace().Items.Any(n => n.Metadata.Name == name)); return client.Run(c => c.ListNamespace().Items.Any(n => n.Metadata.Name == name));
} }
private void CreatePolicy()
{
client.Run(c =>
{
var body = new V1NetworkPolicy
{
Metadata = new V1ObjectMeta
{
Name = "isolate-policy",
NamespaceProperty = K8sTestNamespace
},
Spec = new V1NetworkPolicySpec
{
PodSelector = new V1LabelSelector
{
MatchLabels = GetSelector()
},
PolicyTypes = new[]
{
"Ingress",
"Egress"
},
Ingress = new List<V1NetworkPolicyIngressRule>
{
new V1NetworkPolicyIngressRule
{
FromProperty = new List<V1NetworkPolicyPeer>
{
new V1NetworkPolicyPeer
{
NamespaceSelector = new V1LabelSelector
{
MatchLabels = GetMyNamespaceSelector()
}
}
}
}
},
Egress = new List<V1NetworkPolicyEgressRule>
{
new V1NetworkPolicyEgressRule
{
To = new List<V1NetworkPolicyPeer>
{
new V1NetworkPolicyPeer
{
NamespaceSelector = new V1LabelSelector
{
MatchLabels = GetMyNamespaceSelector()
}
}
}
}
}
}
};
c.CreateNamespacedNetworkPolicy(body, K8sTestNamespace);
});
}
#endregion #endregion
#region Deployment management #region Deployment management
@ -192,12 +255,18 @@ namespace KubernetesWorkflow
return new Dictionary<string, string> { { "codex-test-node", "dist-test-" + workflowNumberSource.WorkflowNumber } }; return new Dictionary<string, string> { { "codex-test-node", "dist-test-" + workflowNumberSource.WorkflowNumber } };
} }
private IDictionary<string, string> GetMyNamespaceSelector()
{
return new Dictionary<string, string> { { "name", "thatisincorrect" } };
}
private V1ObjectMeta CreateDeploymentMetadata() private V1ObjectMeta CreateDeploymentMetadata()
{ {
return new V1ObjectMeta return new V1ObjectMeta
{ {
Name = "deploy-" + workflowNumberSource.WorkflowNumber, Name = "deploy-" + workflowNumberSource.WorkflowNumber,
NamespaceProperty = K8sTestNamespace NamespaceProperty = K8sTestNamespace,
Labels = GetSelector()
}; };
} }

View File

@ -4,23 +4,20 @@ using Utils;
namespace Tests.BasicTests namespace Tests.BasicTests
{ {
[Ignore("not a real test!")] // Warning!
// This is a test to check network-isolation in the test-infrastructure.
// It requires parallelism(2) or greater to run.
[TestFixture] [TestFixture]
public class NetworkIsolationTest : DistTest public class NetworkIsolationTest : DistTest
{ {
private IOnlineCodexNode? node = null; private IOnlineCodexNode? node = null;
// net isolation: only on real cluster?
[Test] [Test]
public void SetUpANodeAndWait() public void SetUpANodeAndWait()
{ {
node = SetupCodexNode(); node = SetupCodexNode();
while (node != null) Time.WaitUntil(() => node == null, TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(5));
{
Time.Sleep(TimeSpan.FromSeconds(5));
}
} }
[Test] [Test]
@ -28,22 +25,21 @@ namespace Tests.BasicTests
{ {
var myNode = SetupCodexNode(); var myNode = SetupCodexNode();
while (node == null) Time.WaitUntil(() => node != null, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(5));
try
{ {
Time.Sleep(TimeSpan.FromSeconds(1)); myNode.ConnectToPeer(node!);
}
catch
{
// Good! This connection should be prohibited by the network isolation policy.
node = null;
return;
} }
myNode.ConnectToPeer(node); Assert.Fail("Connection could be established between two Codex nodes running in different namespaces. " +
"This may cause cross-test interference. Network isolation policy should be applied. Test infra failure.");
var testFile = GenerateTestFile(1.MB());
var contentId = node.UploadFile(testFile);
var downloadedFile = myNode.DownloadContent(contentId);
testFile.AssertIsEqual(downloadedFile);
node = null;
} }
} }
} }