diff --git a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-awssdk.yml b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-awssdk.yml index 63d06e3102..ba2889b031 100644 --- a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-awssdk.yml +++ b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-awssdk.yml @@ -23,7 +23,7 @@ services: localstack: - image: localstack/localstack:stable + image: localstack/localstack:4.14.0@sha256:3ebc37595918b8accb852f8048fef2aff047d465167edd655528065b07bc364a expose: # ports are only available internal to the service, not external so there's no chance for conflicts - "4566" # LocalStack Gateway - "4559" # external services port range @@ -35,6 +35,12 @@ services: volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:4566/_localstack/health"] + interval: 5s + timeout: 5s + retries: 10 + start_period: 10s dynamodb: command: "-jar DynamoDBLocal.jar -inMemory" @@ -42,11 +48,13 @@ services: expose: # ports are only available internal to the service, not external so there's no chance for conflicts - "8000" working_dir: /home/dynamodblocal - + awssdktestapp: depends_on: - - localstack - - dynamodb + localstack: + condition: service_healthy + dynamodb: + condition: service_started container_name: ${CONTAINER_NAME} image: ${CONTAINER_NAME} platform: ${PLATFORM} diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Applications/ContainerApplication.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Applications/ContainerApplication.cs index 0256ad03d8..78a0bec759 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Applications/ContainerApplication.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Applications/ContainerApplication.cs @@ -148,6 +148,7 @@ private void CleanupContainer() Console.WriteLine($"[{AppName} {DateTime.Now}] Cleaning up container and images related to {ContainerName} container."); TestLogger?.WriteLine($"[{AppName}] Cleaning up container and images related to {ContainerName} container."); + var composeDownSucceeded = false; try { var downProc = Process.Start(new ProcessStartInfo @@ -158,57 +159,63 @@ private void CleanupContainer() RedirectStandardError = true, UseShellExecute = false }); - downProc?.WaitForExit(30000); + if (downProc?.WaitForExit(30000) == true) + { + composeDownSucceeded = downProc.ExitCode == 0; + } } catch (Exception ex) { Console.WriteLine($"[{AppName} {DateTime.Now}] Error during compose down: {ex.Message}"); } - // Force remove lingering container with same name if still present - try + // Only force-remove individual resources if compose down didn't clean up successfully + if (!composeDownSucceeded) { - var inspect = Process.Start(new ProcessStartInfo - { - FileName = "docker", - Arguments = $"ps -a --filter name=^/{ContainerName}$ -q", - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false - }); - var output = inspect?.StandardOutput.ReadToEnd(); - inspect?.WaitForExit(5000); - if (!string.IsNullOrWhiteSpace(output)) + // Force remove lingering container with same name if still present + try { - var rm = Process.Start(new ProcessStartInfo + var inspect = Process.Start(new ProcessStartInfo { FileName = "docker", - Arguments = $"rm -f {ContainerName}", + Arguments = $"ps -a --filter name=^/{ContainerName}$ -q", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }); - rm?.WaitForExit(10000); + var output = inspect?.StandardOutput.ReadToEnd(); + inspect?.WaitForExit(5000); + if (!string.IsNullOrWhiteSpace(output)) + { + var rm = Process.Start(new ProcessStartInfo + { + FileName = "docker", + Arguments = $"rm -f {ContainerName}", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false + }); + rm?.WaitForExit(10000); + } } - } - catch { /* ignore */ } + catch { /* ignore */ } - // Attempt removal of lingering default network (compose sometimes races on rapid successive runs) - try - { - var networkName = $"{ContainerName.ToLower()}_default"; - var proc = Process.Start(new ProcessStartInfo + // Attempt removal of lingering default network (compose sometimes races on rapid successive runs) + try { - FileName = "docker", - Arguments = $"network rm {networkName}", - RedirectStandardError = true, - RedirectStandardOutput = true, - UseShellExecute = false - }); - proc?.WaitForExit(5000); + var networkName = $"{ContainerName.ToLower()}_default"; + var proc = Process.Start(new ProcessStartInfo + { + FileName = "docker", + Arguments = $"network rm {networkName}", + RedirectStandardError = true, + RedirectStandardOutput = true, + UseShellExecute = false + }); + proc?.WaitForExit(5000); + } + catch { /* ignore */ } } - catch { /* ignore */ } - #if DEBUG // Cleanup the networks with no attached containers. Mainly for testings on dev laptops - they can build up and block runs. @@ -219,7 +226,8 @@ private void CleanupContainer() protected override void PrepareForStart() { CleanupContainer(); - // Remove any stale network with expected name so compose can recreate it with correct labels + + // Remove any stale network left by a previous crashed run so compose can recreate it cleanly try { var networkName = $"{ContainerName.ToLower()}_default"; @@ -233,7 +241,7 @@ protected override void PrepareForStart() }); netRm?.WaitForExit(5000); } - catch { /* ignore */ } + catch { /* ignore — network may not exist */ } CaptureDockerState("pre-start"); } @@ -362,8 +370,11 @@ void RunAndWrite(string title, string fileName, string args, int timeoutMs = 800 RunAndWrite("containers", "docker", "ps -a --filter name=containertestapp_ --format \"{{.ID}} {{.Names}} {{.Status}}\""); // List networks RunAndWrite("networks", "docker", "network ls --format \"{{.ID}} {{.Name}}\""); - // Inspect the specific expected network (may fail if absent) - RunAndWrite("inspect_target_network", "docker", $"network inspect {ContainerName.ToLower()}_default"); + // Inspect the specific expected network (skip at pre-start since the network hasn't been created yet) + if (stage != "pre-start") + { + RunAndWrite("inspect_target_network", "docker", $"network inspect {ContainerName.ToLower()}_default"); + } // Compose ls (if available) RunAndWrite("compose_projects", "docker", "compose ls"); diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkDynamoDBTest.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkDynamoDBTest.cs index 9e61be591b..5e508248f3 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkDynamoDBTest.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkDynamoDBTest.cs @@ -10,6 +10,7 @@ namespace NewRelic.Agent.ContainerIntegrationTests.Tests.AwsSdk; +[Collection("AwsSdkTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class AwsSdkDynamoDBTest : NewRelicIntegrationTest diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkFirehoseTest.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkFirehoseTest.cs index 314b89ff77..ce0ef14994 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkFirehoseTest.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkFirehoseTest.cs @@ -10,6 +10,7 @@ namespace NewRelic.Agent.ContainerIntegrationTests.Tests.AwsSdk; +[Collection("AwsSdkTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class AwsSdkFirehoseTest : NewRelicIntegrationTest diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkKinesisTest.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkKinesisTest.cs index 16b23dcac2..117b942d45 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkKinesisTest.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkKinesisTest.cs @@ -10,6 +10,7 @@ namespace NewRelic.Agent.ContainerIntegrationTests.Tests.AwsSdk; +[Collection("AwsSdkTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class AwsSdkKinesisTest : NewRelicIntegrationTest diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkMultiServiceTest.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkMultiServiceTest.cs index dc38ff1a49..0ccace40cb 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkMultiServiceTest.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkMultiServiceTest.cs @@ -9,6 +9,7 @@ namespace NewRelic.Agent.ContainerIntegrationTests.Tests.AwsSdk; +[Collection("AwsSdkTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class AwsSdkMultiServiceTest : NewRelicIntegrationTest diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkSQSTest.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkSQSTest.cs index 68382670fc..c63b09807f 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkSQSTest.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/AwsSdk/AwsSdkSQSTest.cs @@ -165,12 +165,15 @@ public void Test() } } +[Collection("AwsSdkTests")] public class AwsSdkSQSTestInitializedCollections : AwsSdkSQSTestBase { public AwsSdkSQSTestInitializedCollections(AwsSdkContainerSQSTestFixture fixture, ITestOutputHelper output) : base(fixture, output, true) { } } + +[Collection("AwsSdkTests")] public class AwsSdkSQSTestNullCollections : AwsSdkSQSTestBase { public AwsSdkSQSTestNullCollections(AwsSdkContainerSQSTestFixture fixture, ITestOutputHelper output) : base(fixture, output, false) diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/KafkaTests.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/KafkaTests.cs index c0f282bdce..e3e8add38f 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/KafkaTests.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/KafkaTests.cs @@ -134,6 +134,7 @@ internal static string GenerateTopic() } } +[Collection("KafkaTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class KafkaDotNet8Test : LinuxKafkaTest @@ -143,6 +144,7 @@ public KafkaDotNet8Test(KafkaDotNet8TestFixture fixture, ITestOutputHelper outpu } } +[Collection("KafkaTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class KafkaDotNet10Test : LinuxKafkaTest diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/MemcachedTests.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/MemcachedTests.cs index 8b6b82fe3a..6dc830fd06 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/MemcachedTests.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/Tests/MemcachedTests.cs @@ -127,6 +127,7 @@ public void Test() } } +[Collection("MemcachedTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class MemcachedDotNet8Test : LinuxMemcachedTest @@ -136,6 +137,7 @@ public MemcachedDotNet8Test(MemcachedDotNet8TestFixture fixture, ITestOutputHelp } } +[Collection("MemcachedTests")] [Trait("Architecture", "amd64")] [Trait("Distro", "Ubuntu")] public class MemcachedDotNet10Test : LinuxMemcachedTest