From a66bbfdee93c9ae7cc325873816c3d2cc5f2c92d Mon Sep 17 00:00:00 2001 From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:14:01 -0600 Subject: [PATCH] test: Refactor container integration tests to reduce flickers (#2104) --- .../docker-compose-kafka.yml | 69 ++++++++++++++++++ .../docker-compose-smoketestapp.yml | 45 ++++++++++++ .../ContainerApplications/docker-compose.yml | 71 +++---------------- .../ContainerIntegrationTests.sln | 2 + .../ContainerFixtures/ContainerApplication.cs | 26 +++---- .../LinuxKafkaTestFixtures.cs | 5 +- .../LinuxKafkaTests.cs | 7 +- 7 files changed, 140 insertions(+), 85 deletions(-) create mode 100644 tests/Agent/IntegrationTests/ContainerApplications/docker-compose-kafka.yml create mode 100644 tests/Agent/IntegrationTests/ContainerApplications/docker-compose-smoketestapp.yml diff --git a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-kafka.yml b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-kafka.yml new file mode 100644 index 000000000..c396295ee --- /dev/null +++ b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-kafka.yml @@ -0,0 +1,69 @@ +version: "3" + +# The following must be set either in environment variables or via a .env file in the same folder as this file: +# +# AGENT_PATH host path to the Agent linux home folder - will map to /usr/local/newrelic-dotnet-agent in the container +# LOG_PATH host path for Agent logfile output - will map to /app/logs in the container +# DISTRO_TAG distro tag for build, not including the architecture suffix - possible values 7.0-bullseye-slim, 7.0-alpine, 7.0-jammy +# TARGET_ARCH the target architecture for the build and run -- either amd64 or arm64 +# PORT external port for the smoketest API +# CONTAINER_NAME The name for the container +# PLATFORM The platform that the service runs on -- linux/amd64 or linux/arm64/v8 +# DOTNET_VERSION The dotnet version number to use (7.0, 8.0, etc) +# TEST_DOCKERFILE The path and dockerfile to use for the service. +# +# and the usual suspects: +# NEW_RELIC_LICENSE_KEY +# NEW_RELIC_HOST +# NEW_RELIC_APP_NAME +# +# +# To build and run, execute `docker compose -f up` +# Alternatively, set COMPOSE_FILE environment variable to the path and omit the -f parameter + +services: + UbuntuX64Kafka1TestApp: + extends: + file: docker-compose-smoketestapp.yml + service: smoketestapp + depends_on: + - kafka-broker + environment: + - NEW_RELIC_KAFKA_TOPIC=${NEW_RELIC_KAFKA_TOPIC} + - NEW_RELIC_KAFKA_CONTAINER_NAME=${NEW_RELIC_KAFKA_CONTAINER_NAME} + + UbuntuX64Kafka2TestApp: + extends: + file: docker-compose-smoketestapp.yml + service: smoketestapp + depends_on: + - kafka-broker + environment: + - NEW_RELIC_KAFKA_TOPIC=${NEW_RELIC_KAFKA_TOPIC} + - NEW_RELIC_KAFKA_CONTAINER_NAME=${NEW_RELIC_KAFKA_CONTAINER_NAME} + + kafka-broker: + image: confluentinc/cp-kafka:7.5.0 + environment: + KAFKA_BROKER_ID: 1 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29092,PLAINTEXT_HOST://${NEW_RELIC_KAFKA_CONTAINER_NAME}:9092 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 + KAFKA_PROCESS_ROLES: broker,controller + KAFKA_NODE_ID: 1 + KAFKA_CONTROLLER_QUORUM_VOTERS: 1@${NEW_RELIC_KAFKA_CONTAINER_NAME}:29093 + KAFKA_LISTENERS: PLAINTEXT://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29092,CONTROLLER://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29093,PLAINTEXT_HOST://:9092 + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER + KAFKA_LOG_DIRS: /tmp/kraft-combined-logs + CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk + + +networks: + default: + driver: bridge + driver_opts: + com.docker.network.bridge.enable_icc: "true" diff --git a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-smoketestapp.yml b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-smoketestapp.yml new file mode 100644 index 000000000..c7c71029e --- /dev/null +++ b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose-smoketestapp.yml @@ -0,0 +1,45 @@ +version: "3" + +# The following must be set either in environment variables or via a .env file in the same folder as this file: +# +# AGENT_PATH host path to the Agent linux home folder - will map to /usr/local/newrelic-dotnet-agent in the container +# LOG_PATH host path for Agent logfile output - will map to /app/logs in the container +# DISTRO_TAG distro tag for build, not including the architecture suffix - possible values 7.0-bullseye-slim, 7.0-alpine, 7.0-jammy +# TARGET_ARCH the target architecture for the build and run -- either amd64 or arm64 +# PORT external port for the smoketest API +# CONTAINER_NAME The name for the container +# PLATFORM The platform that the service runs on -- linux/amd64 or linux/arm64/v8 +# DOTNET_VERSION The dotnet version number to use (7.0, 8.0, etc) +# NETWORK_NAME The network name to use for containers in this app. Should be unique among all running instances. +# TEST_DOCKERFILE The path and dockerfile to use for the service. +# +# and the usual suspects: +# NEW_RELIC_LICENSE_KEY +# NEW_RELIC_HOST +# NEW_RELIC_APP_NAME +# +# +# To build and run, execute `docker compose -f up` +# Alternatively, set COMPOSE_FILE environment variable to the path and omit the -f parameter + +services: + smoketestapp: + container_name: ${CONTAINER_NAME} + image: ${CONTAINER_NAME} + platform: ${PLATFORM} + build: + context: . + dockerfile: ${TEST_DOCKERFILE} + args: + DISTRO_TAG: ${DISTRO_TAG} + TARGET_ARCH: ${TARGET_ARCH} + NEW_RELIC_LICENSE_KEY: ${NEW_RELIC_LICENSE_KEY} + NEW_RELIC_APP_NAME: ${NEW_RELIC_APP_NAME} + NEW_RELIC_HOST: ${NEW_RELIC_HOST} + DOTNET_VERSION: ${DOTNET_VERSION} + APP_DOTNET_VERSION: ${APP_DOTNET_VERSION} + ports: + - "${PORT}:80" + volumes: + - ${AGENT_PATH}:/usr/local/newrelic-dotnet-agent # AGENT_PATH from .env, points to newrelichome_linux_x64 + - ${LOG_PATH}:/app/logs # LOG_PATH from .env, should be a folder unique to this run of the smoketest app diff --git a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose.yml b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose.yml index 384212fa1..58262ec8a 100644 --- a/tests/Agent/IntegrationTests/ContainerApplications/docker-compose.yml +++ b/tests/Agent/IntegrationTests/ContainerApplications/docker-compose.yml @@ -23,104 +23,53 @@ version: "3" # Alternatively, set COMPOSE_FILE environment variable to the path and omit the -f parameter services: - smoketestapp: - container_name: ${CONTAINER_NAME} - image: ${CONTAINER_NAME} - platform: ${PLATFORM} - build: - context: . - dockerfile: ${TEST_DOCKERFILE} - args: - DISTRO_TAG: ${DISTRO_TAG} - TARGET_ARCH: ${TARGET_ARCH} - NEW_RELIC_LICENSE_KEY: ${NEW_RELIC_LICENSE_KEY} - NEW_RELIC_APP_NAME: ${NEW_RELIC_APP_NAME} - NEW_RELIC_HOST: ${NEW_RELIC_HOST} - DOTNET_VERSION: ${DOTNET_VERSION} - APP_DOTNET_VERSION: ${APP_DOTNET_VERSION} - ports: - - "${PORT}:80" - volumes: - - ${AGENT_PATH}:/usr/local/newrelic-dotnet-agent # AGENT_PATH from .env, points to newrelichome_linux_x64 - - ${LOG_PATH}:/app/logs # LOG_PATH from .env, should be a folder unique to this run of the smoketest app DebianX64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp UbuntuX64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp AlpineX64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp DebianArm64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp UbuntuArm64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp CentosX64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp build: dockerfile: SmokeTestApp/Dockerfile.centos CentosArm64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp build: dockerfile: SmokeTestApp/Dockerfile.centos AmazonX64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp build: dockerfile: SmokeTestApp/Dockerfile.amazon AmazonArm64SmokeTestApp: extends: + file: docker-compose-smoketestapp.yml service: smoketestapp build: dockerfile: SmokeTestApp/Dockerfile.centos - - UbuntuX64Kafka1TestApp: - extends: - service: smoketestapp - depends_on: - - kafka-broker - environment: - - NEW_RELIC_KAFKA_TOPIC=${NEW_RELIC_KAFKA_TOPIC} - - NEW_RELIC_KAFKA_CONTAINER_NAME=${NEW_RELIC_KAFKA_CONTAINER_NAME} - - UbuntuX64Kafka2TestApp: - extends: - service: smoketestapp - depends_on: - - kafka-broker - environment: - - NEW_RELIC_KAFKA_TOPIC=${NEW_RELIC_KAFKA_TOPIC} - - NEW_RELIC_KAFKA_CONTAINER_NAME=${NEW_RELIC_KAFKA_CONTAINER_NAME} - - kafka-broker: - image: confluentinc/cp-kafka:7.5.0 - container_name: ${NEW_RELIC_KAFKA_CONTAINER_NAME} - environment: - KAFKA_BROKER_ID: 1 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29092,PLAINTEXT_HOST://${NEW_RELIC_KAFKA_CONTAINER_NAME}:9092 - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 - KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 - KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 - KAFKA_PROCESS_ROLES: broker,controller - KAFKA_NODE_ID: 1 - KAFKA_CONTROLLER_QUORUM_VOTERS: 1@${NEW_RELIC_KAFKA_CONTAINER_NAME}:29093 - KAFKA_LISTENERS: PLAINTEXT://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29092,CONTROLLER://${NEW_RELIC_KAFKA_CONTAINER_NAME}:29093,PLAINTEXT_HOST://:9092 - KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT - KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER - KAFKA_LOG_DIRS: /tmp/kraft-combined-logs - CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk - - + networks: default: - name: ${NETWORK_NAME} driver: bridge driver_opts: com.docker.network.bridge.enable_icc: "true" diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests.sln b/tests/Agent/IntegrationTests/ContainerIntegrationTests.sln index bd86b6585..5c5b8c702 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests.sln +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests.sln @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewRelic.Api.Agent", "..\.. EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_docker", "_docker", "{FB10922F-3CC6-4497-AF53-DF6808380258}" ProjectSection(SolutionItems) = preProject + ContainerApplications\docker-compose-kafka.yml = ContainerApplications\docker-compose-kafka.yml + ContainerApplications\docker-compose-smoketestapp.yml = ContainerApplications\docker-compose-smoketestapp.yml ContainerApplications\docker-compose.yml = ContainerApplications\docker-compose.yml EndProjectSection EndProject diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/ContainerApplication.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/ContainerApplication.cs index 6eaf9a836..b04498890 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/ContainerApplication.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/ContainerApplication.cs @@ -16,6 +16,7 @@ namespace NewRelic.Agent.ContainerIntegrationTests.ContainerFixtures; public class ContainerApplication : RemoteApplication { private readonly string _dockerfile; + private readonly string _dockerComposeFile; private readonly string _dotnetVersion; private readonly string _distroTag; private readonly string _targetArch; @@ -36,13 +37,16 @@ protected override string SourceApplicationDirectoryPath } } - public ContainerApplication(string applicationDirectoryName, string distroTag, Architecture containerArchitecture, string dotnetVersion, string dockerfile) : base(applicationType: ApplicationType.Container, isCoreApp: true) + public ContainerApplication(string applicationDirectoryName, string distroTag, Architecture containerArchitecture, + string dotnetVersion, string dockerfile, string dockerComposeFile = "docker-compose.yml") : base(applicationType: ApplicationType.Container, isCoreApp: true) { ApplicationDirectoryName = applicationDirectoryName; _dockerComposeServiceName = applicationDirectoryName; _distroTag = distroTag; _dotnetVersion = dotnetVersion; _dockerfile = dockerfile; + _dockerComposeFile = dockerComposeFile; + DockerDependencies = new List(); switch (containerArchitecture) @@ -75,7 +79,7 @@ public override void Start(string commandLineArguments, Dictionary 0) - { - foreach (var dep in DockerDependencies) - { - Console.WriteLine($"[{AppName} {DateTime.Now}] Removing dependent container: {dep}."); - TestLogger?.WriteLine($"[{AppName}] Removing dependent container: {dep}."); - Process.Start("docker", $"container rm --force {dep}"); - } - } + Process.Start("docker", $"compose -p {_dockerComposeServiceName.ToLower()} down --rmi local --remove-orphans"); + #if DEBUG // Cleanup the networks with no attached containers. Mainly for testings on dev laptops - they can build up and block runs. diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/LinuxKafkaTestFixtures.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/LinuxKafkaTestFixtures.cs index 54c02e5c5..eefe645e4 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/LinuxKafkaTestFixtures.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/ContainerFixtures/LinuxKafkaTestFixtures.cs @@ -13,8 +13,9 @@ protected LinuxKafkaTestFixtureBase( string distroTag, ContainerApplication.Architecture containerArchitecture, string dockerfile, - string dotnetVersion) : - base(new ContainerApplication(applicationDirectoryName, distroTag, containerArchitecture, dotnetVersion, dockerfile)) + string dotnetVersion, + string dockerComposeFile = "docker-compose-kafka.yml") : + base(new ContainerApplication(applicationDirectoryName, distroTag, containerArchitecture, dotnetVersion, dockerfile, dockerComposeFile)) { } diff --git a/tests/Agent/IntegrationTests/ContainerIntegrationTests/LinuxKafkaTests.cs b/tests/Agent/IntegrationTests/ContainerIntegrationTests/LinuxKafkaTests.cs index dfb6d968d..2c4670b19 100644 --- a/tests/Agent/IntegrationTests/ContainerIntegrationTests/LinuxKafkaTests.cs +++ b/tests/Agent/IntegrationTests/ContainerIntegrationTests/LinuxKafkaTests.cs @@ -18,7 +18,7 @@ public abstract class LinuxKafkaTest : NewRelicIntegrationTest where T : L { private const int TopicNameLength = 15; - internal string _topicName; + private readonly string _topicName; private readonly T _fixture; protected LinuxKafkaTest(T fixture, ITestOutputHelper output) : base(fixture) @@ -27,8 +27,7 @@ protected LinuxKafkaTest(T fixture, ITestOutputHelper output) : base(fixture) _fixture.TestLogger = output; _topicName = GenerateTopic(); - var brokerName = "broker" + _topicName; - ((ContainerApplication)_fixture.RemoteApplication).DockerDependencies.Add(brokerName); + var brokerName = "kafka-broker"; _fixture.Actions(setupConfiguration: () => { @@ -113,7 +112,6 @@ internal static string GenerateTopic() } } -[Collection("Sequential")] public class UbuntuX64Kafka1Test : LinuxKafkaTest { public UbuntuX64Kafka1Test(UbuntuX64Kafka1TestFixture fixture, ITestOutputHelper output) : base(fixture, output) @@ -121,7 +119,6 @@ public UbuntuX64Kafka1Test(UbuntuX64Kafka1TestFixture fixture, ITestOutputHelper } } -[Collection("Sequential")] public class UbuntuX64Kafka2Test : LinuxKafkaTest { public UbuntuX64Kafka2Test(UbuntuX64Kafka2TestFixture fixture, ITestOutputHelper output) : base(fixture, output)