diff --git a/e2e/src/test/java/octopus/teamcity/e2e/dsl/TeamCityFactory.java b/e2e/src/test/java/octopus/teamcity/e2e/dsl/TeamCityFactory.java index 373059da..7f593346 100644 --- a/e2e/src/test/java/octopus/teamcity/e2e/dsl/TeamCityFactory.java +++ b/e2e/src/test/java/octopus/teamcity/e2e/dsl/TeamCityFactory.java @@ -11,6 +11,10 @@ import java.nio.file.StandardCopyOption; import java.time.Duration; import java.util.Iterator; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import com.google.common.io.Resources; import net.lingala.zip4j.ZipFile; @@ -21,11 +25,11 @@ import org.jetbrains.teamcity.rest.TeamCityInstance; import org.jetbrains.teamcity.rest.TeamCityInstanceFactory; import org.testcontainers.Testcontainers; -import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; public class TeamCityFactory { @@ -36,6 +40,11 @@ public class TeamCityFactory { private final Path teamCityDataDir; private final Network dockerNetwork; + private final String TEAMCITY_SERVER_HOST = "server"; + private final int TEAMCITY_SERVER_PORT = 8111; + private final String TEAMCITY_SERVER_URL = + String.format("http://%s:%s", TEAMCITY_SERVER_HOST, TEAMCITY_SERVER_PORT); + public TeamCityFactory(final Path teamCityDataDir, final Network dockerNetwork) { this.teamCityDataDir = teamCityDataDir; this.dockerNetwork = dockerNetwork; @@ -43,7 +52,7 @@ public TeamCityFactory(final Path teamCityDataDir, final Network dockerNetwork) public TeamCityContainers createTeamCityServerAndAgent( final int octopusServerPort, final String octopusServerApiKey, final Path projectZipToInstall) - throws IOException, URISyntaxException { + throws IOException, URISyntaxException, ExecutionException, InterruptedException { final String serverUrl = String.format("http://host.testcontainers.internal:%d", octopusServerPort); Testcontainers.exposeHostPorts(octopusServerPort); @@ -55,7 +64,7 @@ public TeamCityContainers createTeamCityServerAndAgent( final String octopusServerUrl, final String octopusServerApiKey, final Path projectZipToInstall) - throws IOException, URISyntaxException { + throws IOException, URISyntaxException, ExecutionException, InterruptedException { setupDataDir(teamCityDataDir, projectZipToInstall); @@ -66,15 +75,23 @@ public TeamCityContainers createTeamCityServerAndAgent( teamCityDataDir.toString(), "config", "projects", "StepVnext", "project-config.xml"); updateProjectFile(projectFile, octopusServerUrl, octopusServerApiKey); - final GenericContainer teamCityServer = createAndStartServer(); + final GenericContainer teamCityServer = createServerContainer(); + final GenericContainer teamCityAgent = createAgentContainer(); + // Need to pull the containers in parallel + final ExecutorService executor = Executors.newFixedThreadPool(5); + final Future teamcityServerFuture = executor.submit(teamCityServer::start); + final Future teamcityAgentFuture = executor.submit(teamCityAgent::start); + + // wait for teamcityServer to start + teamcityServerFuture.get(); final String teamCityUrl = String.format( "http://%s:%d", teamCityServer.getHost(), teamCityServer.getFirstMappedPort()); LOG.info("TeamCity server running on {}", teamCityUrl); try { - final GenericContainer teamCityAgent = createAndStartAgent(); + teamcityAgentFuture.get(); final String tcServerUrlOnHost = String.format("http://localhost:%d", teamCityServer.getFirstMappedPort()); @@ -83,15 +100,16 @@ public TeamCityContainers createTeamCityServerAndAgent( authoriseAgents(tcInstance); return new TeamCityContainers(teamCityServer, teamCityAgent, tcInstance); } catch (final Exception e) { + LOG.info(teamCityAgent.getLogs()); teamCityServer.stop(); throw e; } } - private GenericContainer createAndStartServer() { + private GenericContainer createServerContainer() { final GenericContainer teamCityServer = new GenericContainer<>(DockerImageName.parse("jetbrains/teamcity-server:2021.2.3")) - .withExposedPorts(8111) + .withExposedPorts(TEAMCITY_SERVER_PORT) .waitingFor(Wait.forLogMessage(".*Super user authentication token.*", 1)) .withNetwork(dockerNetwork) .withNetworkAliases("server") @@ -101,23 +119,21 @@ private GenericContainer createAndStartServer() { "-Droot.log.level=TRACE -Dteamcity.development.mode=true " + "-Doctopus.enable.step.vnext=true") .withStartupTimeout(Duration.ofMinutes(2)) - .withFileSystemBind( - teamCityDataDir.toAbsolutePath().toString(), - "/data/teamcity_server/datadir", - BindMode.READ_WRITE); + .withCopyFileToContainer( + MountableFile.forHostPath(teamCityDataDir.toAbsolutePath().toString()), + "/data/teamcity_server/datadir"); - teamCityServer.start(); return teamCityServer; } - private GenericContainer createAndStartAgent() { + private GenericContainer createAgentContainer() { final GenericContainer teamCityAgent = new GenericContainer<>(DockerImageName.parse("jetbrains/teamcity-agent:2021.2.3")) .withNetwork(dockerNetwork) - .withEnv("SERVER_URL", "http://server:8111") + .withEnv("SERVER_URL", TEAMCITY_SERVER_URL) .waitingFor(Wait.forLogMessage(".*jetbrains.buildServer.AGENT - Agent name was.*", 1)) .withStartupTimeout(Duration.ofMinutes(5)); - teamCityAgent.start(); + return teamCityAgent; } diff --git a/e2e/src/test/java/octopus/teamcity/e2e/test/BuildInformationEndToEndTest.java b/e2e/src/test/java/octopus/teamcity/e2e/test/BuildInformationEndToEndTest.java index c0f2b592..3bfa63e1 100644 --- a/e2e/src/test/java/octopus/teamcity/e2e/test/BuildInformationEndToEndTest.java +++ b/e2e/src/test/java/octopus/teamcity/e2e/test/BuildInformationEndToEndTest.java @@ -28,8 +28,8 @@ import java.time.Duration; import java.time.Instant; import java.util.List; +import java.util.concurrent.ExecutionException; -import com.google.common.collect.Lists; import com.google.common.io.Resources; import octopus.teamcity.e2e.dsl.TeamCityContainers; import octopus.teamcity.e2e.dsl.TeamCityFactory; @@ -54,7 +54,7 @@ public class BuildInformationEndToEndTest { @Test public void buildInformationStepPublishesToOctopusDeploy(@TempDir Path testDirectory) - throws InterruptedException, IOException, URISyntaxException { + throws InterruptedException, IOException, URISyntaxException, ExecutionException { final URL projectsImport = Resources.getResource("TeamCity_StepVnext.zip"); @@ -111,12 +111,7 @@ public void buildInformationStepPublishesToOctopusDeploy(@TempDir Path testDirec assertThat(items.get(0).getProperties().getPackageId()).isEqualTo("mypackage"); } catch (final Exception e) { LOG.info("Failed to execute build"); - LOG.info(teamCityContainers.getAgentContainer().getLogs()); throw e; - } finally { - // Turns out, some files get written to this directory by TC (as the tcuser) - and they need - // to be destroyed. - cleanupContainers(teamCityContainers); } } @@ -136,26 +131,4 @@ private void waitForBuildToFinish(final Build build, final TeamCityInstance tcRe LOG.warn("Build {} failed to complete within expected time limit", build.getId()); throw new RuntimeException("Build Failed to complete within 30 seconds"); } - - private void cleanupContainers(final TeamCityContainers teamCityContainers) { - final List filesToDelete = - Lists.newArrayList( - "/data/teamcity_server/datadir/system/buildserver.tmp", - "/data/teamcity_server/datadir/system/artifacts", - "/data/teamcity_server/datadir/system/caches/plugins.unpacked", - "/data/teamcity_server/datadir/system/caches/pluginsDslCache/src", - "/data/teamcity_server/datadir/system/caches/buildsMetadata/metadataDB.tmp", - "/data/teamcity_server/datadir/system/caches/sources", - "/data/teamcity_server/datadir/system/caches/kotlinDslData", - "/data/teamcity_server/datadir/system/pluginData/avatars"); - - for (final String file : filesToDelete) { - try { - LOG.debug("Removing " + file); - teamCityContainers.getServerContainer().execInContainer("rm", "-rf", file); - } catch (final Exception e) { - LOG.error("Failed to delete " + file); - } - } - } } diff --git a/gradle/versions.gradle b/gradle/versions.gradle index e0bd3cc8..c1e61d3b 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -40,7 +40,7 @@ dependencyManagement { entry 'error_prone_test_helpers' } - dependencySet(group: "org.testcontainers", version: '1.15.3') { + dependencySet(group: "org.testcontainers", version: '1.17.3') { entry 'testcontainers' entry 'junit-jupiter' }