From cd185e425339d324dc2d5a0835bd935fe99f7cdd Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 May 2021 16:49:27 +0200 Subject: [PATCH 01/73] Revert "JPERF-273: Hide untested new API" This reverts commit 71d7136625e9a1425f293786819f893b9bedf7fc. --- CHANGELOG.md | 6 ++++++ .../{ => api}/jira/install/InstalledJira.kt | 4 +++- .../{ => api}/jira/install/JiraInstallation.kt | 5 ++++- .../{ => api}/jira/install/ParallelInstallation.kt | 2 +- .../{ => api}/jira/install/SequentialInstallation.kt | 2 +- .../{ => api}/jira/install/TcpServer.kt | 2 +- .../{ => api}/jira/start/JiraLaunchScript.kt | 4 ++-- .../tools/infrastructure/api/jira/start/JiraStart.kt | 12 ++++++++++++ .../infrastructure/api/jira/start/StartedJira.kt | 8 ++++++++ .../tools/infrastructure/jira/start/JiraStart.kt | 12 ------------ .../tools/infrastructure/jira/start/StartedJira.kt | 8 -------- .../{ => api}/jira/install/JiraLaunchScriptIT.kt | 4 ++-- 12 files changed, 40 insertions(+), 29 deletions(-) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/InstalledJira.kt (87%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/JiraInstallation.kt (71%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/ParallelInstallation.kt (95%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/SequentialInstallation.kt (93%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/TcpServer.kt (84%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/start/JiraLaunchScript.kt (81%) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/StartedJira.kt delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraStart.kt delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/StartedJira.kt rename src/test/kotlin/com/atlassian/performance/tools/infrastructure/{ => api}/jira/install/JiraLaunchScriptIT.kt (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03fd093d..9a129455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -194,10 +194,16 @@ Empty release to test changes in release process. ### Added - Point to remote files on SSH hosts via `RemotePath`. +Progress on [JPERF-273]: +- Allow multiple ways of installing Jira via `JiraInstallation` or starting it via `JiraStart`. +- Represent the information required to use an already installed Jira via `InstalledJira` or `JiraStart` if started. +- Represent a brand-new Jira instance via `EmptyJiraHome`. + ### Fixed - Increase network-level retries for Jira/browser downloads. Decrease flakiness of such downloads on Ubuntu on WSL2. - Download ChromeDriver version that matches installed Chrome version. Fix [JPERF-732]. +[JPERF-273]: https://ecosystem.atlassian.net/browse/JPERF-273 [JPERF-732]: https://ecosystem.atlassian.net/browse/JPERF-732 ## [4.17.5] - 2020-12-15 diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/InstalledJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt similarity index 87% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/InstalledJira.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt index f989223e..0668ea98 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/InstalledJira.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt @@ -1,10 +1,12 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.infrastructure.api.jvm.JavaDevelopmentKit import com.atlassian.performance.tools.infrastructure.api.os.RemotePath /** * Points to an already installed Jira. + * + * @since 4.18.0 */ class InstalledJira( /** diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt similarity index 71% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraInstallation.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index ecf1383b..5f390f47 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -1,7 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import net.jcip.annotations.ThreadSafe +/** + * @since 4.18.0 + */ @ThreadSafe interface JiraInstallation { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt similarity index 95% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/ParallelInstallation.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index 8dcd537e..8f228003 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.concurrency.api.submitWithLogContext import com.atlassian.performance.tools.infrastructure.api.distribution.ProductDistribution diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/SequentialInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt similarity index 93% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/SequentialInstallation.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt index 0d9ca677..7615a397 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/SequentialInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.infrastructure.api.distribution.ProductDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/TcpServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt similarity index 84% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/TcpServer.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt index 13cf3dd3..1b7f1eeb 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/TcpServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.ssh.api.Ssh diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraLaunchScript.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt similarity index 81% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraLaunchScript.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt index 14086413..55e8ec6d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraLaunchScript.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt @@ -1,6 +1,6 @@ -package com.atlassian.performance.tools.infrastructure.jira.start +package com.atlassian.performance.tools.infrastructure.api.jira.start -import com.atlassian.performance.tools.infrastructure.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.ssh.api.Ssh import java.time.Duration diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt new file mode 100644 index 00000000..9f2d9cd8 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt @@ -0,0 +1,12 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import net.jcip.annotations.ThreadSafe + +@ThreadSafe +interface JiraStart { + + fun start( + installed: InstalledJira + ): StartedJira +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/StartedJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/StartedJira.kt new file mode 100644 index 00000000..da6f4955 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/StartedJira.kt @@ -0,0 +1,8 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira + +class StartedJira( + val installed: InstalledJira, + val pid: Int +) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraStart.kt deleted file mode 100644 index 9cb166bb..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/JiraStart.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.jira.start - -import com.atlassian.performance.tools.infrastructure.jira.install.InstalledJira -import net.jcip.annotations.ThreadSafe - -@ThreadSafe -interface JiraStart { - - fun start( - installed: InstalledJira - ): StartedJira -} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/StartedJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/StartedJira.kt deleted file mode 100644 index a7f29f61..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/StartedJira.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.jira.start - -import com.atlassian.performance.tools.infrastructure.jira.install.InstalledJira - -class StartedJira( - val installed: InstalledJira, - val pid: Int -) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraLaunchScriptIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt similarity index 92% rename from src/test/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraLaunchScriptIT.kt rename to src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt index 77c70105..cc0667eb 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/JiraLaunchScriptIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt @@ -1,9 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.jira.install +package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK -import com.atlassian.performance.tools.infrastructure.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.toSsh import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat From 818ef7e44ac9acb851adb894ef73cbb93b32162f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 12 Feb 2021 16:00:01 +0100 Subject: [PATCH 02/73] JPERF-273: Hook into Jira provisioning --- CHANGELOG.md | 6 +- .../jira/install/hook/AsyncProfilerHook.kt | 57 ++++++++++++++ .../api/jira/install/hook/DataCenterHook.kt | 24 ++++++ .../jira/install/hook/DisabledAutoBackup.kt | 15 ++++ .../install/hook/HookedJiraInstallation.kt | 24 ++++++ .../api/jira/install/hook/JiraHomeProperty.kt | 16 ++++ .../api/jira/install/hook/JiraLogs.kt | 28 +++++++ .../api/jira/install/hook/JvmConfig.kt | 29 ++++++++ .../jira/install/hook/LateUbuntuSysstat.kt | 35 +++++++++ .../api/jira/install/hook/PostInstallHook.kt | 21 ++++++ .../api/jira/install/hook/PostInstallHooks.kt | 54 ++++++++++++++ .../api/jira/install/hook/PreInstallHook.kt | 21 ++++++ .../api/jira/install/hook/PreInstallHooks.kt | 40 ++++++++++ .../api/jira/install/hook/SystemLog.kt | 11 +++ .../api/jira/report/FileListing.kt | 16 ++++ .../infrastructure/api/jira/report/Report.kt | 15 ++++ .../infrastructure/api/jira/report/Reports.kt | 18 +++++ .../api/jira/report/StaticReport.kt | 10 +++ .../api/jira/start/hook/AccessLogs.kt | 12 +++ .../api/jira/start/hook/HookedJiraStart.kt | 24 ++++++ .../api/jira/start/hook/JstatHook.kt | 17 +++++ .../api/jira/start/hook/PostStartHook.kt | 21 ++++++ .../api/jira/start/hook/PostStartHooks.kt | 39 ++++++++++ .../api/jira/start/hook/PreStartHook.kt | 21 ++++++ .../api/jira/start/hook/PreStartHooks.kt | 38 ++++++++++ .../api/jira/start/hook/RestUpgrade.kt | 74 +++++++++++++++++++ .../jira/install/hook/ProfilerHook.kt | 41 ++++++++++ .../jira/install/hook/SplunkForwarderHook.kt | 21 ++++++ .../report/RemoteMonitoringProcessReport.kt | 14 ++++ ...LaunchScriptIT.kt => HookedJiraStartIT.kt} | 31 ++++++-- .../jira/install/hook/PreInstallHooksTest.kt | 61 +++++++++++++++ 31 files changed, 846 insertions(+), 8 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Report.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/RemoteMonitoringProcessReport.kt rename src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/{JiraLaunchScriptIT.kt => HookedJiraStartIT.kt} (60%) create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a129455..77dec6ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -194,10 +194,14 @@ Empty release to test changes in release process. ### Added - Point to remote files on SSH hosts via `RemotePath`. -Progress on [JPERF-273]: +Fix [JPERF-273]: - Allow multiple ways of installing Jira via `JiraInstallation` or starting it via `JiraStart`. - Represent the information required to use an already installed Jira via `InstalledJira` or `JiraStart` if started. - Represent a brand-new Jira instance via `EmptyJiraHome`. +- Hook into Jira installation via `PreInstallHooks` and `PostInstallHooks`. +- Hook into Jira start via `PreStartHooks` and `PostStartHooks`. +- Let hooks insert new hooks. +- Locate and download any logs, charts, profiles and other reports via `Report` (rather than hardcoding the paths). ### Fixed - Increase network-level retries for Jira/browser downloads. Decrease flakiness of such downloads on Ubuntu on WSL2. diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt new file mode 100644 index 00000000..5f60deaf --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt @@ -0,0 +1,57 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.net.URI + +class AsyncProfilerHook : PreInstallHook { + + override fun call( + ssh: SshConnection, + server: TcpServer, + hooks: PreInstallHooks + ) { + val directory = "async-profiler" + val downloads = URI("https://github.com/jvm-profiling-tools/async-profiler/releases/download/") + val distribution = downloads.resolve("v1.4/async-profiler-1.4-linux-x64.tar.gz") + ssh.execute("wget -q $distribution") + ssh.execute("mkdir $directory") + ssh.execute("tar -xzf async-profiler-1.4-linux-x64.tar.gz -C $directory") + ssh.execute("sudo sh -c 'echo 1 > /proc/sys/kernel/perf_event_paranoid'") + ssh.execute("sudo sh -c 'echo 0 > /proc/sys/kernel/kptr_restrict'") + val profilerPath = "./$directory/profiler.sh" + val profiler = InstalledAsyncProfiler(profilerPath) + hooks.postStart.insert(profiler) + } +} + +private class InstalledAsyncProfiler( + private val profilerPath: String +) : PostStartHook { + + override fun call( + ssh: SshConnection, + jira: StartedJira, + hooks: PostStartHooks + ) { + ssh.execute("$profilerPath -b 20000000 start ${jira.pid}") + val profiler = StartedAsyncProfiler(jira.pid, profilerPath) + hooks.reports.add(profiler) + } +} + +private class StartedAsyncProfiler( + private val pid: Int, + private val profilerPath: String +) : Report { + + override fun locate(ssh: SshConnection): List { + val flameGraphFile = "flamegraph.svg" + ssh.execute("$profilerPath stop $pid -o svg > $flameGraphFile") + return listOf(flameGraphFile) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt new file mode 100644 index 00000000..4b4b549f --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt @@ -0,0 +1,24 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.SharedHome +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +class DataCenterHook( + private val nodeId: String, + private val sharedHome: SharedHome +) : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + val localSharedHome = sharedHome.localSharedHome + sharedHome.mount(ssh) + val jiraHome = jira.home.path // TODO what's the difference between localSharedHome and jiraHome? should both be hookable? + ssh.execute("echo ehcache.object.port = 40011 >> $jiraHome/cluster.properties") + ssh.execute("echo jira.node.id = $nodeId >> $jiraHome/cluster.properties") + ssh.execute("echo jira.shared.home = `realpath $localSharedHome` >> $jiraHome/cluster.properties") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt new file mode 100644 index 00000000..8cc6e973 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt @@ -0,0 +1,15 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +class DisabledAutoBackup : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + ssh.execute("echo jira.autoexport=false > ${jira.home.path}/jira-config.properties") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt new file mode 100644 index 00000000..e8fc3ae0 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt @@ -0,0 +1,24 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer + +class HookedJiraInstallation( + private val installation: JiraInstallation, + private val hooks: PreInstallHooks +) : JiraInstallation { + + override fun install( + server: TcpServer + ): InstalledJira { + server.ssh.newConnection().use { ssh -> + hooks.call(ssh, server) + } + val installed = installation.install(server) + server.ssh.newConnection().use { ssh -> + hooks.postInstall.call(ssh, installed) + } + return installed + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt new file mode 100644 index 00000000..9d8d1ed4 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt @@ -0,0 +1,16 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +class JiraHomeProperty : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + val properties = "${jira.installation.path}/atlassian-jira/WEB-INF/classes/jira-application.properties" + ssh.execute("echo jira.home=`realpath ${jira.home.path}` > $properties") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt new file mode 100644 index 00000000..ef6f803c --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt @@ -0,0 +1,28 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.nio.file.Path +import java.nio.file.Paths + +class JiraLogs : PostInstallHook { + + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks) { + listOf( + "${jira.home.path}/log/atlassian-jira.log", + "${jira.installation.path}/logs/catalina.out" + ) + .onEach { ensureFile(Paths.get(it), ssh) } + .map { StaticReport(it) } + .forEach { hooks.reports.add(it) } + } + + private fun ensureFile( + path: Path, + ssh: SshConnection + ) { + ssh.execute("mkdir -p ${path.parent!!}") + ssh.execute("touch $path") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt new file mode 100644 index 00000000..d7f68580 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt @@ -0,0 +1,29 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.JiraGcLog +import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig +import com.atlassian.performance.tools.infrastructure.api.jira.SetenvSh +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing +import com.atlassian.performance.tools.ssh.api.SshConnection + +class JvmConfig( + private val config: JiraNodeConfig +) : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + val gcLog = JiraGcLog(jira.installation.path) + SetenvSh(jira.installation.path).setup( + connection = ssh, + config = config, + gcLog = gcLog, + jiraIp = jira.server.ip + ) + val report = FileListing(gcLog.path("*")) + hooks.reports.add(report) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt new file mode 100644 index 00000000..2273c81c --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt @@ -0,0 +1,35 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.Iostat +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.api.os.OsMetric +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.api.os.Vmstat +import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport +import com.atlassian.performance.tools.ssh.api.SshConnection + +class LateUbuntuSysstat : PostInstallHook { + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + val ubuntu = Ubuntu() + ubuntu.install(ssh, listOf("sysstat")) + listOf(Vmstat(), Iostat()) + .map { PostStartOsMetric(it) } + .forEach { hooks.postStart.insert(it) } + } +} + +private class PostStartOsMetric( + private val metric: OsMetric +) : PostStartHook { + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { + val process = metric.start(ssh) + hooks.reports.add(RemoteMonitoringProcessReport(process)) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt new file mode 100644 index 00000000..0fe19b0a --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt @@ -0,0 +1,21 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Intercepts a call after Jira is installed. + */ +interface PostInstallHook { + + /** + * @param [ssh] connects to the [jira] + * @param [jira] points to the installed Jira + * @param [hooks] inserts future hooks and reports + */ + fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt new file mode 100644 index 00000000..0b285cf5 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt @@ -0,0 +1,54 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.jira.install.hook.ProfilerHook +import com.atlassian.performance.tools.infrastructure.jira.install.hook.SplunkForwarderHook +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PostInstallHooks private constructor( + val preStart: PreStartHooks +) { + + private val hooks: Queue = ConcurrentLinkedQueue() + val postStart = preStart.postStart + val reports = postStart.reports + + fun insert( + hook: PostInstallHook + ) { + hooks.add(hook) + } + + internal fun call( + ssh: SshConnection, + jira: InstalledJira + ) { + while (true) { + hooks + .poll() + ?.call(ssh, jira, this) + ?: break + } + } + + companion object Factory { + fun default(): PostInstallHooks = PostInstallHooks(PreStartHooks.default()).apply { + val config = JiraNodeConfig.Builder().build() + listOf( + JiraHomeProperty(), + DisabledAutoBackup(), + JvmConfig(config), + ProfilerHook(config.profiler), + SplunkForwarderHook(config.splunkForwarder), + JiraLogs(), + LateUbuntuSysstat() + ).forEach { insert(it) } + } + + fun empty(): PostInstallHooks = PostInstallHooks(PreStartHooks.empty()) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt new file mode 100644 index 00000000..1e58b1af --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt @@ -0,0 +1,21 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Intercepts a call before Jira is installed. + */ +interface PreInstallHook { + + /** + * @param [ssh] connects to the [server] + * @param [server] will install Jira + * @param [hooks] inserts future hooks and reports + */ + fun call( + ssh: SshConnection, + server: TcpServer, + hooks: PreInstallHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt new file mode 100644 index 00000000..5506de0d --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt @@ -0,0 +1,40 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PreInstallHooks private constructor( + val postInstall: PostInstallHooks +) { + + private val hooks: Queue = ConcurrentLinkedQueue() + val preStart = postInstall.preStart + val postStart = preStart.postStart + val reports = postStart.reports + + fun insert( + hook: PreInstallHook + ) { + hooks.add(hook) + } + + internal fun call( + ssh: SshConnection, + server: TcpServer + ) { + while (true) { + hooks + .poll() + ?.call(ssh, server, this) + ?: break + } + } + + companion object Factory { + fun default(): PreInstallHooks = PreInstallHooks(PostInstallHooks.default()) + + fun empty(): PreInstallHooks = PreInstallHooks(PostInstallHooks.empty()) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt new file mode 100644 index 00000000..861b0ec8 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt @@ -0,0 +1,11 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.ssh.api.SshConnection + +class SystemLog : Report { + + override fun locate(ssh: SshConnection): List { + return listOf("/var/log/syslog") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt new file mode 100644 index 00000000..75979fca --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt @@ -0,0 +1,16 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.report + +import com.atlassian.performance.tools.ssh.api.SshConnection + +class FileListing( + private val pattern: String +) : Report { + + override fun locate( + ssh: SshConnection + ): List = ssh + .execute("ls $pattern") + .output + .lines() + .filter { it.isNotBlank() } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Report.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Report.kt new file mode 100644 index 00000000..65059517 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Report.kt @@ -0,0 +1,15 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.report + +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Reports back about remote events. E.g. points to interesting logs, dumps, charts. + */ +interface Report { + + /** + * @param [ssh] connects to the server, which holds interesting data + * @return interesting file paths, which could be downloaded + */ + fun locate(ssh: SshConnection): List +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt new file mode 100644 index 00000000..bfc8b1cd --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -0,0 +1,18 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.report + +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class Reports { + private val reports: Queue = ConcurrentLinkedQueue() + + fun add( + report: Report + ) { + reports.add(report) + } + + fun list(): Iterable { + return reports.toList() + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt new file mode 100644 index 00000000..da90e4d1 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt @@ -0,0 +1,10 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.report + +import com.atlassian.performance.tools.ssh.api.SshConnection + +class StaticReport( + private val remotePath: String +) : Report { + + override fun locate(ssh: SshConnection): List = listOf(remotePath) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt new file mode 100644 index 00000000..6bc2f30e --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt @@ -0,0 +1,12 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +class AccessLogs : PostStartHook { + + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { + hooks.reports.add(FileListing("${jira.installed.installation.path}/logs/*access*")) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt new file mode 100644 index 00000000..70afbfff --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt @@ -0,0 +1,24 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira + +class HookedJiraStart( + private val start: JiraStart, + private val hooks: PreStartHooks +) : JiraStart { + + override fun start( + installed: InstalledJira + ): StartedJira { + installed.server.ssh.newConnection().use { ssh -> + hooks.call(ssh, installed) + } + val started = start.start(installed) + installed.server.ssh.newConnection().use { ssh -> + hooks.postStart.call(ssh, started) + } + return started + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt new file mode 100644 index 00000000..e4485af4 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt @@ -0,0 +1,17 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport +import com.atlassian.performance.tools.ssh.api.SshConnection + +class JstatHook : PostStartHook { + + override fun call( + ssh: SshConnection, + jira: StartedJira, + hooks: PostStartHooks + ) { + val process = jira.installed.jdk.jstatMonitoring.start(ssh, jira.pid) + hooks.reports.add(RemoteMonitoringProcessReport(process)) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt new file mode 100644 index 00000000..c3c47123 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt @@ -0,0 +1,21 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Intercepts a call after Jira is started. + */ +interface PostStartHook { + + /** + * @param [ssh] connects to the [jira] + * @param [jira] points to the started Jira + * @param [hooks] inserts future reports + */ + fun call( + ssh: SshConnection, + jira: StartedJira, + hooks: PostStartHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt new file mode 100644 index 00000000..21b0b46a --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt @@ -0,0 +1,39 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PostStartHooks private constructor() { + + private val hooks: Queue = ConcurrentLinkedQueue() + val reports = Reports() + + fun insert( + hook: PostStartHook + ) { + hooks.add(hook) + } + + internal fun call( + ssh: SshConnection, + jira: StartedJira + ) { + while (true) { + hooks + .poll() + ?.call(ssh, jira, this) + ?: break + } + } + + companion object Factory { + fun default(): PostStartHooks = empty().apply { + insert(JstatHook()) + } + + fun empty(): PostStartHooks = PostStartHooks() + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt new file mode 100644 index 00000000..d0fa8326 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt @@ -0,0 +1,21 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Intercepts a call before Jira is started. + */ +interface PreStartHook { + + /** + * @param [ssh] connects to the [jira] + * @param [jira] points to the installed Jira + * @param [hooks] inserts future hooks and reports + */ + fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PreStartHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt new file mode 100644 index 00000000..6ce16b42 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt @@ -0,0 +1,38 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PreStartHooks private constructor( + val postStart: PostStartHooks +) { + + private val hooks: Queue = ConcurrentLinkedQueue() + val reports = postStart.reports + + fun insert( + hook: PreStartHook + ) { + hooks.add(hook) + } + + internal fun call( + ssh: SshConnection, + jira: InstalledJira + ) { + while (true) { + hooks + .poll() + ?.call(ssh, jira, this) + ?: break + } + } + + companion object Factory { + fun default() = PreStartHooks(PostStartHooks.default()) + + fun empty() = PreStartHooks(PostStartHooks.empty()) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt new file mode 100644 index 00000000..84aa39f4 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -0,0 +1,74 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.start.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts +import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jvm.ThreadDump +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.net.URI +import java.time.Duration +import java.time.Instant + +class RestUpgrade( + private val timeouts: JiraLaunchTimeouts, + private val adminUsername: String, + private val adminPassword: String +) : PostStartHook { + + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { + val threadDump = ThreadDump(jira.pid, jira.installed.jdk) + val privatePort = jira.installed.server.privatePort + val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$privatePort/rest/api/2/upgrade") + hooks.reports.add(StaticReport("thread-dumps")) + waitForStatusToChange( + statusQuo = "000", + timeout = timeouts.offlineTimeout, + ssh = ssh, + uri = upgradesEndpoint, + threadDump = threadDump + ) + waitForStatusToChange( + statusQuo = "503", + timeout = timeouts.initTimeout, + ssh = ssh, + uri = upgradesEndpoint, + threadDump = threadDump + ) + ssh.execute( + cmd = "curl --silent --retry 6 -X POST $upgradesEndpoint", + timeout = Duration.ofSeconds(15) + ) + waitForStatusToChange( + statusQuo = "303", + timeout = timeouts.upgradeTimeout, + ssh = ssh, + uri = upgradesEndpoint, + threadDump = threadDump + ) + } + + private fun waitForStatusToChange( + statusQuo: String, + uri: URI, + timeout: Duration, + ssh: SshConnection, + threadDump: ThreadDump + ) { + val backoff = Duration.ofSeconds(10) + val deadline = Instant.now() + timeout + while (true) { + val currentStatus = ssh.safeExecute( + cmd = "curl --silent --write-out '%{http_code}' --output /dev/null -X GET $uri", + timeout = timeouts.unresponsivenessTimeout + ).output + if (currentStatus != statusQuo) { + break + } + if (deadline < Instant.now()) { + throw Exception("$uri failed to get out of $statusQuo status within $timeout") + } + threadDump.gather(ssh, "thread-dumps") + Thread.sleep(backoff.toMillis()) + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt new file mode 100644 index 00000000..5b26eaa1 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt @@ -0,0 +1,41 @@ +package com.atlassian.performance.tools.infrastructure.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook +import com.atlassian.performance.tools.infrastructure.api.profiler.Profiler +import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport +import com.atlassian.performance.tools.ssh.api.SshConnection + +/** + * Bridges the [Profiler] SPI with the [PostInstallHook] SPI. + * In general any [Profiler] can be rewritten as a [PreStartHook] or [PostStartHook] without this bridge. + */ +class ProfilerHook( + private val profiler: Profiler +) : PostInstallHook { + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks) { + profiler.install(ssh) + hooks.preStart.postStart.insert(InstalledProfiler(profiler)) + } +} + +private class InstalledProfiler( + private val profiler: Profiler +) : PostStartHook { + + override fun call( + ssh: SshConnection, + jira: StartedJira, + hooks: PostStartHooks + ) { + val process = profiler.start(ssh, jira.pid) + if (process != null) { + hooks.reports.add(RemoteMonitoringProcessReport(process)) + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt new file mode 100644 index 00000000..59c05bd2 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt @@ -0,0 +1,21 @@ +package com.atlassian.performance.tools.infrastructure.jira.install.hook + +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.splunk.SplunkForwarder +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class SplunkForwarderHook( + private val splunk: SplunkForwarder +) : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + splunk.jsonifyLog4j(ssh, "${jira.installation.path}/atlassian-jira/WEB-INF/classes/log4j.properties") + splunk.run(ssh, jira.server.name, "/home/ubuntu/jirahome/log") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/RemoteMonitoringProcessReport.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/RemoteMonitoringProcessReport.kt new file mode 100644 index 00000000..6d904047 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/RemoteMonitoringProcessReport.kt @@ -0,0 +1,14 @@ +package com.atlassian.performance.tools.infrastructure.jira.report + +import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.infrastructure.api.process.RemoteMonitoringProcess +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class RemoteMonitoringProcessReport( + private val process: RemoteMonitoringProcess +) : Report { + override fun locate(ssh: SshConnection): List { + process.stop(ssh) + return listOf(process.getResultPath()) + } +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt similarity index 60% rename from src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt rename to src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt index cc0667eb..2c1b09f3 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraLaunchScriptIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt @@ -2,7 +2,10 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.infrastructure.toSsh import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer @@ -11,22 +14,29 @@ import org.junit.Test import java.nio.file.Files import java.util.function.Consumer -class JiraLaunchScriptIT { +class HookedJiraStartIT { @Test - fun shouldInstallJira() { + fun shouldStartJiraWithHooks() { // given - val installation = ParallelInstallation( - jiraHomeSource = EmptyJiraHome(), - productDistribution = PublicJiraSoftwareDistribution("7.13.0"), - jdk = AdoptOpenJDK() + val hooks = PreInstallHooks.default() + val installation = HookedJiraInstallation( + ParallelInstallation( + jiraHomeSource = EmptyJiraHome(), + productDistribution = PublicJiraSoftwareDistribution("7.13.0"), + jdk = AdoptOpenJDK() + ), + hooks ) - val start = JiraLaunchScript() + val start = HookedJiraStart(JiraLaunchScript(), hooks.preStart) testOnServer { server -> // when val installed = installation.install(server) val started = start.start(installed) + val reports = server.ssh.newConnection().use { ssh -> + hooks.reports.list().flatMap { it.locate(ssh) } + } // then val serverXml = installed @@ -35,6 +45,13 @@ class JiraLaunchScriptIT { .download(Files.createTempFile("downloaded-config", ".xml")) assertThat(serverXml.readText()).contains(" Date: Thu, 17 Oct 2019 14:51:03 +0200 Subject: [PATCH 03/73] Add `DockerMysqlServer` From f620975196b21b02d9431c9eee64b6a4c09c25a7 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 18 Oct 2019 15:34:47 +0200 Subject: [PATCH 04/73] Introduce pre- and post- instance hooks --- .../api/jira/instance/PostInstanceHook.kt | 15 +++++++++++ .../api/jira/instance/PostInstanceHooks.kt | 26 +++++++++++++++++++ .../api/jira/instance/PreInstanceHook.kt | 11 ++++++++ .../api/jira/instance/PreInstanceHooks.kt | 26 +++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt new file mode 100644 index 00000000..48dcb0f8 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt @@ -0,0 +1,15 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import java.net.URI + +interface PostInstanceHook { + + /** + * @param [instance] a standalone Jira Server node or a Jira Data Center cluster + * @param [hooks] inserts future hooks and reports + */ + fun call( + instance: URI, + hooks: PostInstanceHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt new file mode 100644 index 00000000..f519425e --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt @@ -0,0 +1,26 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import java.net.URI +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PostInstanceHooks( + val nodes: List +) { + + private val hooks: Queue = ConcurrentLinkedQueue() + + fun insert(hook: PostInstanceHook) { + hooks.add(hook) + } + + fun call(instance: URI) { + while (true) { + hooks + .poll() + ?.call(instance, this) + ?: break + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt new file mode 100644 index 00000000..31c4c777 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt @@ -0,0 +1,11 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +interface PreInstanceHook { + + /** + * @param [hooks] inserts future hooks and reports + */ + fun call( + hooks: PreInstanceHooks + ) +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt new file mode 100644 index 00000000..bd898228 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt @@ -0,0 +1,26 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue + +class PreInstanceHooks( + val nodes: List +) { + + private val hooks: Queue = ConcurrentLinkedQueue() + val postInstance = PostInstanceHooks(nodes) + + fun hook(hook: PreInstanceHook) { + hooks.add(hook) + } + + fun call() { + while (true) { + hooks + .poll() + ?.call(this) + ?: break + } + } +} From 6992a85ee8793fea5ba21a58ff45c61fad2a2abc Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 21 Oct 2019 15:33:00 +0200 Subject: [PATCH 05/73] Turn `MySqlDatabase` into a hook Turn `PostgresDatabase` into a hook too. --- .../api/database/DatabaseIpConfig.kt | 25 ++++++ .../api/database/DockerMysqlServer.kt | 80 +++++++++++++++++++ .../api/database/DockerPostgresServer.kt | 66 +++++++++++++++ .../api/database/MysqlConnector.kt | 29 +++++++ 4 files changed, 200 insertions(+) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt new file mode 100644 index 00000000..7fb79d0a --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt @@ -0,0 +1,25 @@ +package com.atlassian.performance.tools.infrastructure.api.database + +import com.atlassian.performance.tools.infrastructure.api.Sed +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.ssh.api.SshConnection + +class DatabaseIpConfig( + private val databaseIp: String +) : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + Sed().replace( + connection = ssh, + expression = "(.*(@(//)?|//))" + "([^:/]+)" + "(.*)", + output = """\1$databaseIp\5""", + file = "${jira.home}/dbconfig.xml" + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt new file mode 100644 index 00000000..086ed972 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -0,0 +1,80 @@ +package com.atlassian.performance.tools.infrastructure.api.database + +import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.database.Mysql +import com.atlassian.performance.tools.infrastructure.database.SshSqlClient +import com.atlassian.performance.tools.ssh.api.Ssh +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.net.URI +import java.util.function.Supplier + +class DockerMysqlServer private constructor( + private val serverSupplier: Supplier, + private val source: DatasetPackage, + private val maxConnections: Int +) : PreInstanceHook { + + override fun call(hooks: PreInstanceHooks) { + val server = serverSupplier.get() + val client = server.ssh.newConnection().use { setup(it) } + + hooks.nodes.forEach { node -> + node.postInstall.insert(DatabaseIpConfig(server.ip)) + node.postInstall.insert(MysqlConnector()) + } + hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) + } + + private fun setup(ssh: SshConnection): SshSqlClient { + val mysqlDataLocation = source.download(ssh) + Mysql.container( + dataDir = mysqlDataLocation, + extraParameters = emptyArray(), + extraArguments = arrayOf( + "--skip-grant-tables", // Recovery mode, as some datasets give no permissions to their root DB user + "--max_connections=$maxConnections" + ) + ).run(ssh) + val client = Mysql.installClient(ssh) + Mysql.awaitDatabase(ssh) + return client + } + + class Builder( + private var serverSupplier: Supplier, + private var source: DatasetPackage + ) { + + private var maxConnections: Int = 151 + + fun serverSupplier(serverSupplier: Supplier) = apply { this.serverSupplier = serverSupplier } + fun source(source: DatasetPackage) = apply { this.source = source } + fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } + + fun build(): DockerMysqlServer = DockerMysqlServer( + serverSupplier, + source, + maxConnections + ) + } + + private class FixJiraUriViaMysql( + private val client: SshSqlClient, + private val ssh: Ssh + ) : PostInstanceHook { + + override fun call(instance: URI, hooks: PostInstanceHooks) { + ssh.newConnection().use { ssh -> + val db = "jiradb" + val update = "UPDATE $db.propertystring SET propertyvalue = '$instance'" + val where = "WHERE id IN (select id from $db.propertyentry where property_key like '%baseurl%')" + client.runSql(ssh, "$update $where;") + } + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt new file mode 100644 index 00000000..5e7a2947 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt @@ -0,0 +1,66 @@ +package com.atlassian.performance.tools.infrastructure.api.database + +import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage +import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.ssh.api.SshConnection +import org.apache.logging.log4j.LogManager +import org.apache.logging.log4j.Logger +import java.time.Duration.ofMinutes +import java.time.Duration.ofSeconds +import java.util.function.Supplier + +class DockerPostgresServer private constructor( + private val serverSupplier: Supplier, + private val source: DatasetPackage, + private val maxConnections: Int +) : PreInstanceHook { + + private val logger: Logger = LogManager.getLogger(this::class.java) + + override fun call(hooks: PreInstanceHooks) { + val server = serverSupplier.get() + server.ssh.newConnection().use { setup(it) } + hooks.nodes.forEach { node -> + node.postInstall.insert(DatabaseIpConfig(server.ip)) + } + } + + private fun setup(ssh: SshConnection) { + val data = source.download(ssh) + val containerName = DockerContainer.Builder() + .imageName("postgres:9.6.15") + .pullTimeout(ofMinutes(5)) + .parameters("-p 5432:5432", "-v `realpath $data`:/${TODO("download and mount Postgres data")}") + .arguments("-c 'listen_addresses='*''", "-c 'max_connections=$maxConnections'") + .build() + .run(ssh) + Thread.sleep(ofSeconds(15).toMillis()) + ssh.execute("sudo docker exec -u postgres $containerName psql --command \"CREATE USER jira WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN PASSWORD 'jira';\"") + ssh.execute("sudo docker exec -u postgres $containerName createdb -E UNICODE -l C -T template0 -O jira jira") + /** + * TODO Check logs for the following entry + * `LOG: database system is ready to accept connections` + */ + Thread.sleep(ofSeconds(15).toMillis()) + } + + class Builder( + private var serverSupplier: Supplier, + private var source: DatasetPackage + ) { + private var maxConnections: Int = 200 + + fun serverSupplier(serverSupplier: Supplier) = apply { this.serverSupplier = serverSupplier } + fun source(source: DatasetPackage) = apply { this.source = source } + fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } + + fun build(): DockerPostgresServer = DockerPostgresServer( + serverSupplier, + source, + maxConnections + ) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt new file mode 100644 index 00000000..edc0c8d1 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt @@ -0,0 +1,29 @@ +package com.atlassian.performance.tools.infrastructure.api.database + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction +import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.time.Duration + +class MysqlConnector : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks + ) { + val connector = "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz" + IdempotentAction( + description = "Download MySQL connector", + action = { ssh.execute("wget -q $connector") } + ).retry( + maxAttempts = 3, + backoff = StaticBackoff(Duration.ofSeconds(5)) + ) + ssh.execute("tar -xzf mysql-connector-java-5.1.40.tar.gz") + ssh.execute("cp mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${jira.installation}/lib") + } +} \ No newline at end of file From fa23f13c0c257673a7a5f8b33ad98a00c14d15ab Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 21 Oct 2019 17:10:59 +0200 Subject: [PATCH 06/73] Respect the `TcpServer.publicPort` in MySQL --- .../infrastructure/api/database/DockerMysqlServer.kt | 8 ++++---- .../performance/tools/infrastructure/database/MySql.kt | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 086ed972..08ff71b5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -21,8 +21,7 @@ class DockerMysqlServer private constructor( override fun call(hooks: PreInstanceHooks) { val server = serverSupplier.get() - val client = server.ssh.newConnection().use { setup(it) } - + val client = server.ssh.newConnection().use { setup(it, server.publicPort) } hooks.nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.ip)) node.postInstall.insert(MysqlConnector()) @@ -30,7 +29,7 @@ class DockerMysqlServer private constructor( hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) } - private fun setup(ssh: SshConnection): SshSqlClient { + private fun setup(ssh: SshConnection, publicPort: Int): SshSqlClient { val mysqlDataLocation = source.download(ssh) Mysql.container( dataDir = mysqlDataLocation, @@ -38,7 +37,8 @@ class DockerMysqlServer private constructor( extraArguments = arrayOf( "--skip-grant-tables", // Recovery mode, as some datasets give no permissions to their root DB user "--max_connections=$maxConnections" - ) + ), + hostPort = publicPort ).run(ssh) val client = Mysql.installClient(ssh) Mysql.awaitDatabase(ssh) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index c48843e3..c6815757 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -37,12 +37,13 @@ internal object Mysql { fun container( dataDir: String, extraParameters: Array, - extraArguments: Array + extraArguments: Array, + hostPort: Int = 3306 ) = DockerContainer.Builder() .imageName("mysql:5.7.32") .pullTimeout(Duration.ofMinutes(5)) .parameters( - "-p 3306:3306", + "-p $hostPort:3306", "-v `realpath $dataDir`:/var/lib/mysql", *extraParameters ) From e7f1e42ab6d18b4f2f406fe842638563c7fdf56f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 21 Oct 2019 18:08:13 +0200 Subject: [PATCH 07/73] Fix `RestUpgrade` `Report` --- .../tools/infrastructure/api/jira/report/StaticReport.kt | 6 ++++++ .../tools/infrastructure/api/jira/start/hook/RestUpgrade.kt | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt index da90e4d1..16edfafa 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/StaticReport.kt @@ -2,6 +2,12 @@ package com.atlassian.performance.tools.infrastructure.api.jira.report import com.atlassian.performance.tools.ssh.api.SshConnection +/** + * Points to a remote SSH **file**. For directories use a [FileListing] instead. + * + * @param [remotePath] Points to a file on a remote system. + * Relative to the SSH shell default directory (predominantly the user home directory). + */ class StaticReport( private val remotePath: String ) : Report { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index 84aa39f4..d89e8443 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -1,7 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts -import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport +import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jvm.ThreadDump import com.atlassian.performance.tools.ssh.api.SshConnection @@ -19,7 +19,7 @@ class RestUpgrade( val threadDump = ThreadDump(jira.pid, jira.installed.jdk) val privatePort = jira.installed.server.privatePort val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$privatePort/rest/api/2/upgrade") - hooks.reports.add(StaticReport("thread-dumps")) + hooks.reports.add(FileListing("thread-dumps/*")) waitForStatusToChange( statusQuo = "000", timeout = timeouts.offlineTimeout, From 8d773244fcfaa5589a1a1bedb93553965c5e02c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kwidzi=C5=84ski?= Date: Fri, 12 Mar 2021 11:47:16 +0100 Subject: [PATCH 08/73] WIP test Data Center hooks --- .../jira/provision/JiraNodeProvisioning.kt | 52 +++++++++++++++++++ .../api/jira/install/HookedJiraStartIT.kt | 50 ++++++++++++++++-- 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt new file mode 100644 index 00000000..fa177670 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt @@ -0,0 +1,52 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.provision + +import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution +import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource +import com.atlassian.performance.tools.infrastructure.api.jira.hook.JiraNodeHooks +import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.HookedJiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.JiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.ParallelInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.HookedJiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.JiraLaunchScript +import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.JiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart +import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK +import net.jcip.annotations.NotThreadSafe + +class JiraNodeProvisioning private constructor( + val hooks: PreInstallHooks, + val installation: JiraInstallation, + val start: JiraStart +) { + + @NotThreadSafe + class Builder { + private var hooks: PreInstallHooks = PreInstallHooks.default() + private var installation: JiraInstallation = HookedJiraInstallation( + ParallelInstallation( + EmptyJiraHome(), + PublicJiraSoftwareDistribution("7.13.0"), + OracleJDK() + ), + hooks + ) + private var start: JiraStart = HookedJiraStart(JiraLaunchScript()) + + fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } + fun installation(installation: JiraInstallation) = apply { this.installation = installation } + fun start(start: JiraStart) = apply { this.start = start } + + fun build() = JiraNodeProvisioning( + hooks = hooks, + installation = installation, + start = start + ) + } +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt index 2c1b09f3..f0e2096f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt @@ -30,7 +30,7 @@ class HookedJiraStartIT { ) val start = HookedJiraStart(JiraLaunchScript(), hooks.preStart) - testOnServer { server -> + testOnServer("jira", 8080) { server -> // when val installed = installation.install(server) val started = start.start(installed) @@ -55,8 +55,50 @@ class HookedJiraStartIT { } } - private fun testOnServer(test: (TcpServer) -> T) { - val privatePort = 8080 + @Test + fun shouldStartDataCenter() { + // given + val hooks = PreInstallHooks.default() + val installation = HookedJiraInstallation( + ParallelInstallation( + jiraHomeSource = EmptyJiraHome(), + productDistribution = PublicJiraSoftwareDistribution("7.13.0"), + jdk = AdoptOpenJDK() + ), + hooks + ) + val start = HookedJiraStart(JiraLaunchScript(), hooks.preStart) + + testOnServer("jira1", 8080) { jira1 -> + testOnServer("jira2", 8080) { jira2 -> + testOnServer("mysql", 3306) { mysql -> + // when + val installed = installation.install(jira1) + val started = start.start(installed) + val reports = jira1.ssh.newConnection().use { ssh -> + hooks.reports.list().flatMap { it.locate(ssh) } + } + + // then + val serverXml = installed + .installation + .resolve("conf/server.xml") + .download(Files.createTempFile("downloaded-config", ".xml")) + assertThat(serverXml.readText()).contains(" testOnServer(name: String, privatePort: Int, test: (TcpServer) -> T) { val container = SshUbuntuContainer.Builder() .customization(Consumer { it.addExposedPort(privatePort) }) .build() @@ -65,7 +107,7 @@ class HookedJiraStartIT { "localhost", sshUbuntu.container.getMappedPort(privatePort), privatePort, - "my-jira", + name, sshUbuntu.toSsh() ) test(server) From 6654f676de30408ac2a04b80159428b6988e2a1d Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 12 Mar 2021 17:55:15 +0100 Subject: [PATCH 09/73] WIP include Jira instances Include overall Data Center plan with hook timings. Plans should be reusable with different ways of getting a `TcpHost`: * new via Docker * new via AWS * existing machines This commit injects an `Infrastructure` SPI to reuse a plan with different infra, but to prove the concept, it has to fit the current CloudFormation stack in aws-infrastructure / 2-nodes-dc*.yaml The API smells a little, because a big one-shot CFN stack is split into multiple fine-grained methods. Alternative API could be: `fun plan(host: TcpHost) : JiraNodePlan` Other matters to resolve: * loadbalancer (plan?) API * getting results out of DC instance and node hooks --- .../infrastructure/api/Infrastructure.kt | 11 ++ .../api/database/DockerMysqlServer.kt | 20 +-- .../api/database/DockerPostgresServer.kt | 21 +-- .../api/jira/install/InstalledJira.kt | 2 +- .../api/jira/install/JiraInstallation.kt | 6 +- .../api/jira/install/ParallelInstallation.kt | 6 +- .../jira/install/SequentialInstallation.kt | 6 +- .../jira/install/{TcpServer.kt => TcpHost.kt} | 2 +- .../jira/install/hook/AsyncProfilerHook.kt | 8 +- .../install/hook/HookedJiraInstallation.kt | 12 +- .../api/jira/install/hook/JvmConfig.kt | 2 +- .../api/jira/install/hook/PreInstallHook.kt | 12 +- .../api/jira/install/hook/PreInstallHooks.kt | 8 +- .../api/jira/instance/JiraDataCenterPlan.kt | 69 +++++++ .../api/jira/instance/JiraInstance.kt | 7 + .../api/jira/instance/JiraServerPlan.kt | 64 +++++++ .../api/jira/instance/PreInstanceHooks.kt | 2 +- .../infrastructure/api/jira/node/JiraNode.kt | 8 + .../JiraNodePlan.kt} | 21 +-- .../api/jira/start/hook/HookedJiraStart.kt | 4 +- .../api/jira/start/hook/RestUpgrade.kt | 2 +- .../tools/infrastructure/database/MySql.kt | 5 +- .../jira/install/hook/SplunkForwarderHook.kt | 2 +- .../api/DockerInfrastructure.kt | 45 +++++ .../api/jira/install/HookedJiraStartIT.kt | 168 ++++++++++-------- .../jira/install/hook/PreInstallHooksTest.kt | 8 +- 26 files changed, 374 insertions(+), 147 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/{TcpServer.kt => TcpHost.kt} (96%) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/{provision/JiraNodeProvisioning.kt => node/JiraNodePlan.kt} (69%) create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt new file mode 100644 index 00000000..219d74e4 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -0,0 +1,11 @@ +package com.atlassian.performance.tools.infrastructure.api + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan + +interface Infrastructure { + fun serve(jiraNodePlans: List): List + fun serve(port: Int, name: String): TcpHost + fun releaseResources() +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 08ff71b5..f21f5aff 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -1,7 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.database +import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook @@ -11,17 +12,16 @@ import com.atlassian.performance.tools.infrastructure.database.SshSqlClient import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection import java.net.URI -import java.util.function.Supplier class DockerMysqlServer private constructor( - private val serverSupplier: Supplier, + private val infrastructure: Infrastructure, private val source: DatasetPackage, private val maxConnections: Int ) : PreInstanceHook { override fun call(hooks: PreInstanceHooks) { - val server = serverSupplier.get() - val client = server.ssh.newConnection().use { setup(it, server.publicPort) } + val server = infrastructure.serve(3306, "mysql") + val client = server.ssh.newConnection().use { setup(it, server) } hooks.nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.ip)) node.postInstall.insert(MysqlConnector()) @@ -29,7 +29,7 @@ class DockerMysqlServer private constructor( hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) } - private fun setup(ssh: SshConnection, publicPort: Int): SshSqlClient { + private fun setup(ssh: SshConnection, server: TcpHost): SshSqlClient { val mysqlDataLocation = source.download(ssh) Mysql.container( dataDir = mysqlDataLocation, @@ -38,7 +38,7 @@ class DockerMysqlServer private constructor( "--skip-grant-tables", // Recovery mode, as some datasets give no permissions to their root DB user "--max_connections=$maxConnections" ), - hostPort = publicPort + host = server ).run(ssh) val client = Mysql.installClient(ssh) Mysql.awaitDatabase(ssh) @@ -46,18 +46,18 @@ class DockerMysqlServer private constructor( } class Builder( - private var serverSupplier: Supplier, + private var infrastructure: Infrastructure, private var source: DatasetPackage ) { private var maxConnections: Int = 151 - fun serverSupplier(serverSupplier: Supplier) = apply { this.serverSupplier = serverSupplier } + fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } fun source(source: DatasetPackage) = apply { this.source = source } fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } fun build(): DockerMysqlServer = DockerMysqlServer( - serverSupplier, + infrastructure, source, maxConnections ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt index 5e7a2947..bdcc6698 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt @@ -1,8 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.database +import com.atlassian.performance.tools.infrastructure.api.Infrastructure + import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.ssh.api.SshConnection @@ -10,10 +12,9 @@ import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import java.time.Duration.ofMinutes import java.time.Duration.ofSeconds -import java.util.function.Supplier class DockerPostgresServer private constructor( - private val serverSupplier: Supplier, +private val infrastructure: Infrastructure, private val source: DatasetPackage, private val maxConnections: Int ) : PreInstanceHook { @@ -21,19 +22,19 @@ class DockerPostgresServer private constructor( private val logger: Logger = LogManager.getLogger(this::class.java) override fun call(hooks: PreInstanceHooks) { - val server = serverSupplier.get() - server.ssh.newConnection().use { setup(it) } + val server = infrastructure.serve(5432, "postgres") + server.ssh.newConnection().use { setup(it, server) } hooks.nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.ip)) } } - private fun setup(ssh: SshConnection) { + private fun setup(ssh: SshConnection, server: TcpHost) { val data = source.download(ssh) val containerName = DockerContainer.Builder() .imageName("postgres:9.6.15") .pullTimeout(ofMinutes(5)) - .parameters("-p 5432:5432", "-v `realpath $data`:/${TODO("download and mount Postgres data")}") + .parameters(with(server) {"-p $publicPort:$privatePort"}, "-v `realpath $data`:/${TODO("download and mount Postgres data")}") .arguments("-c 'listen_addresses='*''", "-c 'max_connections=$maxConnections'") .build() .run(ssh) @@ -48,17 +49,17 @@ class DockerPostgresServer private constructor( } class Builder( - private var serverSupplier: Supplier, + private var infrastructure: Infrastructure, private var source: DatasetPackage ) { private var maxConnections: Int = 200 - fun serverSupplier(serverSupplier: Supplier) = apply { this.serverSupplier = serverSupplier } + fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } fun source(source: DatasetPackage) = apply { this.source = source } fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } fun build(): DockerPostgresServer = DockerPostgresServer( - serverSupplier, + infrastructure, source, maxConnections ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt index 0668ea98..1845ac86 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt @@ -24,5 +24,5 @@ class InstalledJira( /** * Hosts Jira. Specifies sockets used by Jira to handle requests. */ - val server: TcpServer + val host: TcpHost ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index 5f390f47..05bd3d96 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -9,11 +9,11 @@ import net.jcip.annotations.ThreadSafe interface JiraInstallation { /** - * Installs Jira on [server]. + * Installs Jira on [host]. * - * @param [server] will host the Jira + * @param [host] will host the Jira */ fun install( - server: TcpServer + host: TcpHost ): InstalledJira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index 8f228003..03af91c0 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -15,9 +15,9 @@ class ParallelInstallation( ) : JiraInstallation { override fun install( - server: TcpServer + host: TcpHost ): InstalledJira { - server.ssh.newConnection().use { ssh -> + host.ssh.newConnection().use { ssh -> val pool = Executors.newCachedThreadPool { runnable -> Thread(runnable, "jira-installation-${runnable.hashCode()}") } @@ -30,7 +30,7 @@ class ParallelInstallation( val java = pool.submitWithLogContext("java") { jdk.also { it.install(ssh) } } - val jira = InstalledJira(home.get(), product.get(), java.get(), server) + val jira = InstalledJira(home.get(), product.get(), java.get(), host) pool.shutdownNow() return jira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt index 7615a397..382c82e8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt @@ -13,13 +13,13 @@ class SequentialInstallation( ) : JiraInstallation { override fun install( - server: TcpServer + host: TcpHost ): InstalledJira { - server.ssh.newConnection().use { ssh -> + host.ssh.newConnection().use { ssh -> val installation = productDistribution.installRemotely(ssh, ".") val home = jiraHomeSource.downloadRemotely(ssh) jdk.install(ssh) - return InstalledJira(home, installation, jdk, server) + return InstalledJira(home, installation, jdk, host) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt similarity index 96% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt index 1b7f1eeb..fc2aa038 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt @@ -5,7 +5,7 @@ import com.atlassian.performance.tools.ssh.api.Ssh /** * Has open TCP sockets. */ -class TcpServer( +class TcpHost( val ip: String, val publicPort: Int, val privatePort: Int, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt index 5f60deaf..95688f98 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.report.Report import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook @@ -11,9 +11,9 @@ import java.net.URI class AsyncProfilerHook : PreInstallHook { override fun call( - ssh: SshConnection, - server: TcpServer, - hooks: PreInstallHooks + ssh: SshConnection, + host: TcpHost, + hooks: PreInstallHooks ) { val directory = "async-profiler" val downloads = URI("https://github.com/jvm-profiling-tools/async-profiler/releases/download/") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt index e8fc3ae0..a7633b23 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost class HookedJiraInstallation( private val installation: JiraInstallation, @@ -10,13 +10,13 @@ class HookedJiraInstallation( ) : JiraInstallation { override fun install( - server: TcpServer + host: TcpHost ): InstalledJira { - server.ssh.newConnection().use { ssh -> - hooks.call(ssh, server) + host.ssh.newConnection().use { ssh -> + hooks.call(ssh, host) } - val installed = installation.install(server) - server.ssh.newConnection().use { ssh -> + val installed = installation.install(host) + host.ssh.newConnection().use { ssh -> hooks.postInstall.call(ssh, installed) } return installed diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt index d7f68580..7c72be25 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt @@ -21,7 +21,7 @@ class JvmConfig( connection = ssh, config = config, gcLog = gcLog, - jiraIp = jira.server.ip + jiraIp = jira.host.ip ) val report = FileListing(gcLog.path("*")) hooks.reports.add(report) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt index 1e58b1af..e51cfd64 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.ssh.api.SshConnection /** @@ -9,13 +9,13 @@ import com.atlassian.performance.tools.ssh.api.SshConnection interface PreInstallHook { /** - * @param [ssh] connects to the [server] - * @param [server] will install Jira + * @param [ssh] connects to the [host] + * @param [host] will install Jira * @param [hooks] inserts future hooks and reports */ fun call( - ssh: SshConnection, - server: TcpServer, - hooks: PreInstallHooks + ssh: SshConnection, + host: TcpHost, + hooks: PreInstallHooks ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt index 5506de0d..84842cff 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.ssh.api.SshConnection import java.util.* import java.util.concurrent.ConcurrentLinkedQueue @@ -21,13 +21,13 @@ class PreInstallHooks private constructor( } internal fun call( - ssh: SshConnection, - server: TcpServer + ssh: SshConnection, + host: TcpHost ) { while (true) { hooks .poll() - ?.call(ssh, server, this) + ?.call(ssh, host, this) ?: break } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt new file mode 100644 index 00000000..97de16e6 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -0,0 +1,69 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer +import java.net.URI +import java.time.Duration +import java.util.function.Supplier + +class JiraDataCenterPlan constructor( + val nodePlans: List, + val instanceHooks: PreInstanceHooks, + val loadBalancerSupplier: Supplier, + val infrastructure: Infrastructure +) : Supplier { + + private val loadBalancingPatience = Duration.ofMinutes(5) + + override fun get(): JiraDataCenter { + instanceHooks.call() + val started = infrastructure.serve(nodePlans).map { jiraNode -> + jiraNode + .plan + .installation + .install(jiraNode.host) + .let { jiraNode.plan.start.start(it) } + } + val loadBalancer = loadBalancerSupplier.get() + instanceHooks.postInstance.call(loadBalancer.uri) + loadBalancer.waitUntilHealthy(loadBalancingPatience) + return JiraDataCenter(started, loadBalancer) + } + + class JiraDataCenter( + val nodes: List, + val loadBalancer: LoadBalancer + ) : JiraInstance { + override val address: URI + get() = loadBalancer.uri + } +// +// class Builder( +// private var jiraNode: TcpServer +// ) { +// private var hooks: PreInstallHooks = PreInstallHooks.default() +// private var installation: JiraInstallation = HookedJiraInstallation( +// ParallelInstallation( +// EmptyJiraHome(), +// PublicJiraSoftwareDistribution("7.13.0"), +// OracleJDK() +// ), +// hooks +// ) +// private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) +// +// fun jiraNode(jiraNode: TcpServer) = apply { this.jiraNode = jiraNode } +// fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation +// fun installation(installation: JiraInstallation) = apply { this.installation = installation } +// fun start(start: JiraStart) = apply { this.start = start } +// +// fun build() = JiraDataCenterPlan( +// jiraNode = jiraNode, +// hooks = hooks, +// installation = installation, +// start = start +// ) +// } +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt new file mode 100644 index 00000000..8d2f4e3c --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt @@ -0,0 +1,7 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import java.net.URI + +interface JiraInstance { + val address: URI +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt new file mode 100644 index 00000000..7d1ad934 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -0,0 +1,64 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution +import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart +import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK +import java.net.URI +import java.util.function.Supplier + +class JiraServerPlan private constructor( + private val infrastructure: Infrastructure, + val hooks: PreInstallHooks, + val installation: JiraInstallation, + val start: JiraStart +) : Supplier { + + override fun get(): JiraServer { + val jiraNode = infrastructure.serve(8080, "jira-node") + val installed = installation.install(jiraNode) + val started = start.start(installed) + return JiraServer(started) + } + + class JiraServer( + val node: StartedJira + ) : JiraInstance { + override val address: URI = node.installed.host.run { URI("http://$ip:$publicPort/") } + } + + class Builder( + private var infrastructure: Infrastructure + ) { + private var hooks: PreInstallHooks = PreInstallHooks.default() + private var installation: JiraInstallation = HookedJiraInstallation( + ParallelInstallation( + EmptyJiraHome(), + PublicJiraSoftwareDistribution("7.13.0"), + OracleJDK() + ), + hooks + ) + private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) + + fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } + fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation + fun installation(installation: JiraInstallation) = apply { this.installation = installation } + fun start(start: JiraStart) = apply { this.start = start } + + fun build() = JiraServerPlan( + infrastructure = infrastructure, + hooks = hooks, + installation = installation, + start = start + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt index bd898228..238db71a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt @@ -11,7 +11,7 @@ class PreInstanceHooks( private val hooks: Queue = ConcurrentLinkedQueue() val postInstance = PostInstanceHooks(nodes) - fun hook(hook: PreInstanceHook) { + fun insert(hook: PreInstanceHook) { hooks.add(hook) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt new file mode 100644 index 00000000..3e0edb01 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt @@ -0,0 +1,8 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.node + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost + +class JiraNode constructor( + val host: TcpHost, + val plan: JiraNodePlan +) \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt similarity index 69% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt index fa177670..f0b0e746 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/provision/JiraNodeProvisioning.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt @@ -1,17 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.provision +package com.atlassian.performance.tools.infrastructure.api.jira.node import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome -import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource -import com.atlassian.performance.tools.infrastructure.api.jira.hook.JiraNodeHooks -import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.HookedJiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.JiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.hook.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.HookedJiraStart -import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.JiraLaunchScript -import com.atlassian.performance.tools.infrastructure.api.jira.hook.start.JiraStart import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript @@ -20,12 +13,14 @@ import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.Hooked import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK import net.jcip.annotations.NotThreadSafe -class JiraNodeProvisioning private constructor( +class JiraNodePlan private constructor( val hooks: PreInstallHooks, val installation: JiraInstallation, val start: JiraStart ) { + fun materialize(host: TcpHost) = JiraNode(host, this) + @NotThreadSafe class Builder { private var hooks: PreInstallHooks = PreInstallHooks.default() @@ -37,13 +32,13 @@ class JiraNodeProvisioning private constructor( ), hooks ) - private var start: JiraStart = HookedJiraStart(JiraLaunchScript()) + private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) - fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } + fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation fun installation(installation: JiraInstallation) = apply { this.installation = installation } fun start(start: JiraStart) = apply { this.start = start } - fun build() = JiraNodeProvisioning( + fun build() = JiraNodePlan( hooks = hooks, installation = installation, start = start diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt index 70afbfff..911c2b43 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt @@ -12,11 +12,11 @@ class HookedJiraStart( override fun start( installed: InstalledJira ): StartedJira { - installed.server.ssh.newConnection().use { ssh -> + installed.host.ssh.newConnection().use { ssh -> hooks.call(ssh, installed) } val started = start.start(installed) - installed.server.ssh.newConnection().use { ssh -> + installed.host.ssh.newConnection().use { ssh -> hooks.postStart.call(ssh, started) } return started diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index d89e8443..f1239d3a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -17,7 +17,7 @@ class RestUpgrade( override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { val threadDump = ThreadDump(jira.pid, jira.installed.jdk) - val privatePort = jira.installed.server.privatePort + val privatePort = jira.installed.host.privatePort val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$privatePort/rest/api/2/upgrade") hooks.reports.add(FileListing("thread-dumps/*")) waitForStatusToChange( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index c6815757..c1dedea8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.ssh.api.SshConnection import org.apache.logging.log4j.LogManager @@ -38,12 +39,12 @@ internal object Mysql { dataDir: String, extraParameters: Array, extraArguments: Array, - hostPort: Int = 3306 + host: TcpHost? = null ) = DockerContainer.Builder() .imageName("mysql:5.7.32") .pullTimeout(Duration.ofMinutes(5)) .parameters( - "-p $hostPort:3306", + host?.let { "-p ${it.publicPort}:${it.privatePort}" } ?: "-p 3306:3306", "-v `realpath $dataDir`:/var/lib/mysql", *extraParameters ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt index 59c05bd2..78282a69 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt @@ -16,6 +16,6 @@ internal class SplunkForwarderHook( hooks: PostInstallHooks ) { splunk.jsonifyLog4j(ssh, "${jira.installation.path}/atlassian-jira/WEB-INF/classes/log4j.properties") - splunk.run(ssh, jira.server.name, "/home/ubuntu/jirahome/log") + splunk.run(ssh, jira.host.name, "/home/ubuntu/jirahome/log") } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt new file mode 100644 index 00000000..019ead0e --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -0,0 +1,45 @@ +package com.atlassian.performance.tools.infrastructure.api + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer +import java.util.* +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.function.Consumer + +internal class DockerInfrastructure : Infrastructure { + + private val allocatedResources: Queue = ConcurrentLinkedQueue() + + override fun serve(jiraNodePlans: List): List { + return jiraNodePlans.mapIndexed { nodeIndex, plan -> + plan.materialize(serve(8080, "jira-node-$nodeIndex")) + } + } + + override fun serve(port: Int, name: String): TcpHost { + val container = SshUbuntuContainer(Consumer { + it.addExposedPort(port) + }) + val sshUbuntu = container.start() + allocatedResources.offer(sshUbuntu) + return TcpHost( + "localhost", + sshUbuntu.container.getMappedPort(port), + port, + name, + sshUbuntu.toSsh() + ) + } + + override fun releaseResources() { + while (true) { + allocatedResources + .poll() + ?.use {} + ?: break + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt index f0e2096f..90a83eea 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt @@ -1,21 +1,44 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer +import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraDataCenterPlan +import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraServerPlan +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat +import org.junit.After +import org.junit.Before import org.junit.Test +import java.net.URI import java.nio.file.Files -import java.util.function.Consumer +import java.time.Duration +import java.util.* +import java.util.function.Supplier class HookedJiraStartIT { + private lateinit var infrastructure: Infrastructure + + @Before + fun setUp() { + infrastructure = DockerInfrastructure() + } + + @After + fun tearDown() { + infrastructure.releaseResources() + } + @Test fun shouldStartJiraWithHooks() { // given @@ -30,21 +53,83 @@ class HookedJiraStartIT { ) val start = HookedJiraStart(JiraLaunchScript(), hooks.preStart) - testOnServer("jira", 8080) { server -> - // when - val installed = installation.install(server) - val started = start.start(installed) - val reports = server.ssh.newConnection().use { ssh -> - hooks.reports.list().flatMap { it.locate(ssh) } + // when + val jiraServer = JiraServerPlan.Builder(infrastructure) + .installation(installation) + .start(start) + .hooks(hooks) + .build() + .get() + + val host = jiraServer.node.installed.host + val reports = host.ssh.newConnection().use { ssh -> + hooks.reports.list().flatMap { it.locate(ssh) } + } + + // then + val serverXml = jiraServer + .node + .installed + .installation + .resolve("conf/server.xml") + .download(Files.createTempFile("downloaded-config", ".xml")) + assertThat(serverXml.readText()).contains(" + HttpDatasetPackage( + uri = uri.resolve("database.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) } + instanceHooks.insert(DockerMysqlServer.Builder(infrastructure, smallJiraSeven).build()) + val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) - // then + // when + val dataCenter = dcPlan.get() + val reports = dataCenter.nodes.ssh.newConnection().use { ssh -> + nodeHooks.reports.list().flatMap { it.locate(ssh) } + } + + // then + dataCenter.nodes.forEach { node -> + val installed = node.installed val serverXml = installed .installation .resolve("conf/server.xml") .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" - testOnServer("jira2", 8080) { jira2 -> - testOnServer("mysql", 3306) { mysql -> - // when - val installed = installation.install(jira1) - val started = start.start(installed) - val reports = jira1.ssh.newConnection().use { ssh -> - hooks.reports.list().flatMap { it.locate(ssh) } - } - - // then - val serverXml = installed - .installation - .resolve("conf/server.xml") - .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" testOnServer(name: String, privatePort: Int, test: (TcpServer) -> T) { - val container = SshUbuntuContainer.Builder() - .customization(Consumer { it.addExposedPort(privatePort) }) - .build() - container.start().use { sshUbuntu -> - val server = TcpServer( - "localhost", - sshUbuntu.container.getMappedPort(privatePort), - privatePort, - name, - sshUbuntu.toSsh() - ) - test(server) - } - } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index 9e5b8bef..eb6dd82a 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpServer +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.mock.UnimplementedSshConnection import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection @@ -12,7 +12,7 @@ import java.nio.file.Paths class PreInstallHooksTest { private val dummySsh = Ssh(SshHost("localhost", "dummyUser", Paths.get("dummyKey"))) - private val dummyServer = TcpServer("doesn't matter", 123, "fake-server", dummySsh) + private val dummyServer = TcpHost("doesn't matter", 123, "fake-server", dummySsh) @Test fun shouldInsertDuringListing() { @@ -47,7 +47,7 @@ private class CountingHook : PreInstallHook { var count = 0 - override fun call(ssh: SshConnection, server: TcpServer, hooks: PreInstallHooks) { + override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks) { count++ } } @@ -55,7 +55,7 @@ private class CountingHook : PreInstallHook { private class InsertingHook( private val hook: PreInstallHook ) : PreInstallHook { - override fun call(ssh: SshConnection, server: TcpServer, hooks: PreInstallHooks) { + override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks) { hooks.insert(hook) } } From 6113a5cbf808d8d2ddeba23c0511f7bc8fe7ac40 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 26 Mar 2021 17:27:55 +0100 Subject: [PATCH 10/73] JPERF-273: Download reports even if a plan fails Download reports per host. --- .../api/database/DatabaseIpConfig.kt | 6 +- .../api/database/DockerMysqlServer.kt | 25 +-- .../api/database/DockerPostgresServer.kt | 9 +- .../api/database/MysqlConnector.kt | 4 +- .../tools/infrastructure/api/docker/Docker.kt | 62 ++++++++ .../api/jira/install/JiraInstallation.kt | 5 +- .../api/jira/install/ParallelInstallation.kt | 4 +- .../jira/install/SequentialInstallation.kt | 4 +- .../api/jira/install/TcpHost.kt | 15 +- .../jira/install/hook/AsyncProfilerHook.kt | 13 +- .../api/jira/install/hook/DataCenterHook.kt | 4 +- .../jira/install/hook/DisabledAutoBackup.kt | 4 +- .../api/jira/install/hook/JiraHomeProperty.kt | 4 +- .../api/jira/install/hook/JiraLogs.kt | 5 +- .../api/jira/install/hook/JvmConfig.kt | 6 +- .../jira/install/hook/LateUbuntuSysstat.kt | 8 +- .../api/jira/install/hook/PostInstallHook.kt | 7 +- .../api/jira/install/hook/PostInstallHooks.kt | 7 +- .../api/jira/install/hook/PreInstallHook.kt | 11 +- .../api/jira/install/hook/PreInstallHooks.kt | 13 +- .../api/jira/install/hook/SystemLog.kt | 10 +- .../api/jira/instance/JiraDataCenterPlan.kt | 90 ++++++----- .../api/jira/instance/JiraInstance.kt | 2 + .../api/jira/instance/JiraInstancePlan.kt | 8 + .../api/jira/instance/JiraServerPlan.kt | 65 +++----- .../api/jira/instance/PostInstanceHook.kt | 10 +- .../api/jira/instance/PostInstanceHooks.kt | 17 ++- .../api/jira/instance/PreInstanceHook.kt | 11 +- .../api/jira/instance/PreInstanceHooks.kt | 15 +- .../api/jira/node/JiraNodePlan.kt | 31 ++-- .../api/jira/report/FileListing.kt | 10 +- .../infrastructure/api/jira/report/Reports.kt | 44 +++++- .../api/jira/start/JiraLaunchScript.kt | 4 +- .../api/jira/start/JiraStart.kt | 10 +- .../api/jira/start/hook/AccessLogs.kt | 9 +- .../api/jira/start/hook/JstatHook.kt | 6 +- .../api/jira/start/hook/PostStartHook.kt | 7 +- .../api/jira/start/hook/PostStartHooks.kt | 6 +- .../api/jira/start/hook/PreStartHook.kt | 7 +- .../api/jira/start/hook/PreStartHooks.kt | 11 +- .../api/jira/start/hook/RestUpgrade.kt | 5 +- .../tools/infrastructure/database/MySql.kt | 2 +- .../infrastructure/database/SshMysqlClient.kt | 10 +- .../install/hook/HookedJiraInstallation.kt | 13 +- .../jira/install/hook/ProfilerHook.kt | 8 +- .../jira/install/hook/SplunkForwarderHook.kt | 6 +- .../jira/start/hook/HookedJiraStart.kt | 13 +- .../tools/infrastructure/Datasets.kt | 18 +++ .../api/DockerInfrastructure.kt | 3 +- .../api/jira/install/HookedJiraStartIT.kt | 142 ------------------ .../jira/install/hook/PreInstallHooksTest.kt | 11 +- .../api/jira/instance/JiraDataCenterPlanIT.kt | 83 ++++++++++ .../api/jira/instance/JiraServerPlanIT.kt | 80 ++++++++++ 53 files changed, 604 insertions(+), 379 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => }/jira/install/hook/HookedJiraInstallation.kt (56%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => }/jira/start/hook/HookedJiraStart.kt (55%) create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt delete mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt index 7fb79d0a..da00606b 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt @@ -4,6 +4,7 @@ import com.atlassian.performance.tools.infrastructure.api.Sed import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class DatabaseIpConfig( @@ -13,13 +14,14 @@ class DatabaseIpConfig( override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { Sed().replace( connection = ssh, expression = "(.*(@(//)?|//))" + "([^:/]+)" + "(.*)", output = """\1$databaseIp\5""", - file = "${jira.home}/dbconfig.xml" + file = "${jira.home.path}/dbconfig.xml" ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index f21f5aff..08a21bab 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -3,15 +3,15 @@ package com.atlassian.performance.tools.infrastructure.api.database import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.* +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.database.Mysql +import com.atlassian.performance.tools.infrastructure.database.SshMysqlClient import com.atlassian.performance.tools.infrastructure.database.SshSqlClient import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection -import java.net.URI class DockerMysqlServer private constructor( private val infrastructure: Infrastructure, @@ -19,10 +19,14 @@ class DockerMysqlServer private constructor( private val maxConnections: Int ) : PreInstanceHook { - override fun call(hooks: PreInstanceHooks) { + override fun call( + nodes: List, + hooks: PreInstanceHooks, + reports: Reports + ) { val server = infrastructure.serve(3306, "mysql") val client = server.ssh.newConnection().use { setup(it, server) } - hooks.nodes.forEach { node -> + nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.ip)) node.postInstall.insert(MysqlConnector()) } @@ -40,7 +44,8 @@ class DockerMysqlServer private constructor( ), host = server ).run(ssh) - val client = Mysql.installClient(ssh) + Ubuntu().install(ssh, listOf("mysql-client")) + val client = SshMysqlClient("127.0.0.1", server.privatePort) Mysql.awaitDatabase(ssh) return client } @@ -68,10 +73,10 @@ class DockerMysqlServer private constructor( private val ssh: Ssh ) : PostInstanceHook { - override fun call(instance: URI, hooks: PostInstanceHooks) { + override fun call(instance: JiraInstance, hooks: PostInstanceHooks, reports: Reports) { ssh.newConnection().use { ssh -> val db = "jiradb" - val update = "UPDATE $db.propertystring SET propertyvalue = '$instance'" + val update = "UPDATE $db.propertystring SET propertyvalue = '${instance.address}'" val where = "WHERE id IN (select id from $db.propertyentry where property_key like '%baseurl%')" client.runSql(ssh, "$update $where;") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt index bdcc6698..572c1fd5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt @@ -5,8 +5,10 @@ import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger @@ -21,10 +23,11 @@ private val infrastructure: Infrastructure, private val logger: Logger = LogManager.getLogger(this::class.java) - override fun call(hooks: PreInstanceHooks) { + override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { + val server = infrastructure.serve(5432, "postgres") server.ssh.newConnection().use { setup(it, server) } - hooks.nodes.forEach { node -> + nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.ip)) } } @@ -34,7 +37,7 @@ private val infrastructure: Infrastructure, val containerName = DockerContainer.Builder() .imageName("postgres:9.6.15") .pullTimeout(ofMinutes(5)) - .parameters(with(server) {"-p $publicPort:$privatePort"}, "-v `realpath $data`:/${TODO("download and mount Postgres data")}") + .parameters(with(server) {"-p $privatePort:$publicPort"}, "-v `realpath $data`:/${TODO("download and mount Postgres data")}") .arguments("-c 'listen_addresses='*''", "-c 'max_connections=$maxConnections'") .build() .run(ssh) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt index edc0c8d1..4aa5cd5b 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt @@ -3,6 +3,7 @@ package com.atlassian.performance.tools.infrastructure.api.database import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection @@ -13,7 +14,8 @@ class MysqlConnector : PostInstallHook { override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { val connector = "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz" IdempotentAction( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt new file mode 100644 index 00000000..dc79ca6d --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt @@ -0,0 +1,62 @@ +package com.atlassian.performance.tools.infrastructure.api.docker + +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction +import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.time.Duration + +class Docker private constructor( + private val dependencyPackagesTimeout: Duration, + private val mainPackageTimeout: Duration +) { + + private val ubuntu = Ubuntu() + + /** + * See the [official guide](https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#install-docker-ce). + */ + fun install( + ssh: SshConnection + ) { + ubuntu.install( + ssh = ssh, + packages = listOf( + "apt-transport-https", + "ca-certificates", + "curl" + ), + timeout = dependencyPackagesTimeout + ) + ubuntu.addKey(ssh, "7EA0A9C3F273FCD8") + + val release = ubuntu.getDistributionCodename(ssh) + ubuntu.addRepository( + ssh, + "deb [arch=amd64] https://download.docker.com/linux/ubuntu $release stable", + "docker" + ); + + val version = "5:19.03.13~3-0~ubuntu-$release" + ubuntu.install( + ssh = ssh, + packages = listOf("docker-ce=$version"), + timeout = mainPackageTimeout + ) + ssh.execute("sudo service docker status || sudo service docker start") + IdempotentAction("poll docker") { + ssh.execute("sudo docker ps") + }.retry(2, StaticBackoff(Duration.ofSeconds(1))) + } + + class Builder { + + private var dependencyPackagesTimeout: Duration = Duration.ofMinutes(2) + private var mainPackageTimeout: Duration = Duration.ofMinutes(5) + + fun build(): Docker = Docker( + dependencyPackagesTimeout, + mainPackageTimeout + ) + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index 05bd3d96..71c0f488 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import net.jcip.annotations.ThreadSafe /** @@ -12,8 +13,10 @@ interface JiraInstallation { * Installs Jira on [host]. * * @param [host] will host the Jira + * @param [reports] accumulates reports */ fun install( - host: TcpHost + host: TcpHost, + reports: Reports ): InstalledJira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index 03af91c0..452f1bea 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -3,6 +3,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.concurrency.api.submitWithLogContext import com.atlassian.performance.tools.infrastructure.api.distribution.ProductDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jvm.JavaDevelopmentKit import com.atlassian.performance.tools.infrastructure.downloadRemotely import com.atlassian.performance.tools.infrastructure.installRemotely @@ -15,7 +16,8 @@ class ParallelInstallation( ) : JiraInstallation { override fun install( - host: TcpHost + host: TcpHost, + reports: Reports ): InstalledJira { host.ssh.newConnection().use { ssh -> val pool = Executors.newCachedThreadPool { runnable -> diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt index 382c82e8..c5d124d3 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install import com.atlassian.performance.tools.infrastructure.api.distribution.ProductDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jvm.JavaDevelopmentKit import com.atlassian.performance.tools.infrastructure.downloadRemotely import com.atlassian.performance.tools.infrastructure.installRemotely @@ -13,7 +14,8 @@ class SequentialInstallation( ) : JiraInstallation { override fun install( - host: TcpHost + host: TcpHost, + reports: Reports ): InstalledJira { host.ssh.newConnection().use { ssh -> val installation = productDistribution.installRemotely(ssh, ".") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt index fc2aa038..83b3df2f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt @@ -11,17 +11,4 @@ class TcpHost( val privatePort: Int, val name: String, val ssh: Ssh -) { - constructor( - ip: String, - port: Int, - name: String, - ssh: Ssh - ) : this( - ip, - port, - port, - name, - ssh - ) -} +) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt index 95688f98..186453e7 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks @@ -11,9 +12,10 @@ import java.net.URI class AsyncProfilerHook : PreInstallHook { override fun call( - ssh: SshConnection, - host: TcpHost, - hooks: PreInstallHooks + ssh: SshConnection, + host: TcpHost, + hooks: PreInstallHooks, + reports: Reports ) { val directory = "async-profiler" val downloads = URI("https://github.com/jvm-profiling-tools/async-profiler/releases/download/") @@ -36,11 +38,12 @@ private class InstalledAsyncProfiler( override fun call( ssh: SshConnection, jira: StartedJira, - hooks: PostStartHooks + hooks: PostStartHooks, + reports: Reports ) { ssh.execute("$profilerPath -b 20000000 start ${jira.pid}") val profiler = StartedAsyncProfiler(jira.pid, profilerPath) - hooks.reports.add(profiler) + reports.add(profiler, jira.installed.host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt index 4b4b549f..5ec19a6d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.SharedHome import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class DataCenterHook( @@ -12,7 +13,8 @@ class DataCenterHook( override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { val localSharedHome = sharedHome.localSharedHome sharedHome.mount(ssh) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt index 8cc6e973..164da451 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class DisabledAutoBackup : PostInstallHook { @@ -8,7 +9,8 @@ class DisabledAutoBackup : PostInstallHook { override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { ssh.execute("echo jira.autoexport=false > ${jira.home.path}/jira-config.properties") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt index 9d8d1ed4..b09991b5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class JiraHomeProperty : PostInstallHook { @@ -8,7 +9,8 @@ class JiraHomeProperty : PostInstallHook { override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { val properties = "${jira.installation.path}/atlassian-jira/WEB-INF/classes/jira-application.properties" ssh.execute("echo jira.home=`realpath ${jira.home.path}` > $properties") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt index ef6f803c..683f5389 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection import java.nio.file.Path @@ -8,14 +9,14 @@ import java.nio.file.Paths class JiraLogs : PostInstallHook { - override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks) { + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { listOf( "${jira.home.path}/log/atlassian-jira.log", "${jira.installation.path}/logs/catalina.out" ) .onEach { ensureFile(Paths.get(it), ssh) } .map { StaticReport(it) } - .forEach { hooks.reports.add(it) } + .forEach { reports.add(it, jira.host) } } private fun ensureFile( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt index 7c72be25..9fe8d5a7 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt @@ -5,6 +5,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig import com.atlassian.performance.tools.infrastructure.api.jira.SetenvSh import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class JvmConfig( @@ -14,7 +15,8 @@ class JvmConfig( override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { val gcLog = JiraGcLog(jira.installation.path) SetenvSh(jira.installation.path).setup( @@ -24,6 +26,6 @@ class JvmConfig( jiraIp = jira.host.ip ) val report = FileListing(gcLog.path("*")) - hooks.reports.add(report) + reports.add(report, jira.host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt index 2273c81c..26f327e2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.Iostat import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks @@ -15,7 +16,8 @@ class LateUbuntuSysstat : PostInstallHook { override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { val ubuntu = Ubuntu() ubuntu.install(ssh, listOf("sysstat")) @@ -28,8 +30,8 @@ class LateUbuntuSysstat : PostInstallHook { private class PostStartOsMetric( private val metric: OsMetric ) : PostStartHook { - override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val process = metric.start(ssh) - hooks.reports.add(RemoteMonitoringProcessReport(process)) + reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt index 0fe19b0a..c95cd0cb 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection /** @@ -11,11 +12,13 @@ interface PostInstallHook { /** * @param [ssh] connects to the [jira] * @param [jira] points to the installed Jira - * @param [hooks] inserts future hooks and reports + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt index 0b285cf5..37088763 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks import com.atlassian.performance.tools.infrastructure.jira.install.hook.ProfilerHook import com.atlassian.performance.tools.infrastructure.jira.install.hook.SplunkForwarderHook @@ -15,7 +16,6 @@ class PostInstallHooks private constructor( private val hooks: Queue = ConcurrentLinkedQueue() val postStart = preStart.postStart - val reports = postStart.reports fun insert( hook: PostInstallHook @@ -25,12 +25,13 @@ class PostInstallHooks private constructor( internal fun call( ssh: SshConnection, - jira: InstalledJira + jira: InstalledJira, + reports: Reports ) { while (true) { hooks .poll() - ?.call(ssh, jira, this) + ?.call(ssh, jira, this, reports) ?: break } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt index e51cfd64..b9be4a39 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection /** @@ -11,11 +12,13 @@ interface PreInstallHook { /** * @param [ssh] connects to the [host] * @param [host] will install Jira - * @param [hooks] inserts future hooks and reports + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( - ssh: SshConnection, - host: TcpHost, - hooks: PreInstallHooks + ssh: SshConnection, + host: TcpHost, + hooks: PreInstallHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt index 84842cff..58e256fa 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection import java.util.* import java.util.concurrent.ConcurrentLinkedQueue @@ -12,7 +13,6 @@ class PreInstallHooks private constructor( private val hooks: Queue = ConcurrentLinkedQueue() val preStart = postInstall.preStart val postStart = preStart.postStart - val reports = postStart.reports fun insert( hook: PreInstallHook @@ -21,19 +21,22 @@ class PreInstallHooks private constructor( } internal fun call( - ssh: SshConnection, - host: TcpHost + ssh: SshConnection, + host: TcpHost, + reports: Reports ) { while (true) { hooks .poll() - ?.call(ssh, host, this) + ?.call(ssh, host, this, reports) ?: break } } companion object Factory { - fun default(): PreInstallHooks = PreInstallHooks(PostInstallHooks.default()) + fun default(): PreInstallHooks = PreInstallHooks(PostInstallHooks.default()).apply { + insert(SystemLog()) + } fun empty(): PreInstallHooks = PreInstallHooks(PostInstallHooks.empty()) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt index 861b0ec8..b3a50fd4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt @@ -1,11 +1,13 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection -class SystemLog : Report { +class SystemLog : PreInstallHook { - override fun locate(ssh: SshConnection): List { - return listOf("/var/log/syslog") + override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks, reports: Reports) { + reports.add(StaticReport("/var/log/syslog"), host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 97de16e6..ac5be1ca 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -1,69 +1,79 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer import java.net.URI import java.time.Duration import java.util.function.Supplier +import kotlin.streams.asStream +import kotlin.streams.toList class JiraDataCenterPlan constructor( val nodePlans: List, val instanceHooks: PreInstanceHooks, val loadBalancerSupplier: Supplier, val infrastructure: Infrastructure -) : Supplier { - +) : JiraInstancePlan { + + private val reports: Reports = Reports() private val loadBalancingPatience = Duration.ofMinutes(5) - override fun get(): JiraDataCenter { - instanceHooks.call() - val started = infrastructure.serve(nodePlans).map { jiraNode -> + override fun materialize(): JiraInstance { + instanceHooks.call(nodePlans.map { it.hooks }, reports) + val nodes = infrastructure.serve(nodePlans) + val installed = installInParallel(nodes) + val started = installed.map { it.start(reports) } + val loadBalancer = loadBalancerSupplier.get() + val instance = JiraDataCenter(started, loadBalancer) + instanceHooks.postInstance.call(instance, reports) + loadBalancer.waitUntilHealthy(loadBalancingPatience) + return instance + } + + override fun report(): Reports = reports.copy() + + private fun installInParallel(nodes: List) = nodes + .asSequence() + .asStream() + .parallel() + .map { jiraNode -> jiraNode .plan .installation - .install(jiraNode.host) - .let { jiraNode.plan.start.start(it) } + .install(jiraNode.host, reports) + .let { installedJira -> InstalledJiraNode(installedJira, jiraNode.plan) } + } + .toList() + + private class InstalledJiraNode( + private val installedJira: InstalledJira, + private val nodePlan: JiraNodePlan + ) { + fun start(reports: Reports): StartedJira { + return nodePlan.start.start(installedJira, reports) } - val loadBalancer = loadBalancerSupplier.get() - instanceHooks.postInstance.call(loadBalancer.uri) - loadBalancer.waitUntilHealthy(loadBalancingPatience) - return JiraDataCenter(started, loadBalancer) } - class JiraDataCenter( - val nodes: List, - val loadBalancer: LoadBalancer + private class JiraDataCenter( + override val nodes: List, + private val loadBalancer: LoadBalancer ) : JiraInstance { override val address: URI get() = loadBalancer.uri } + + class Builder( + private var infrastructure: Infrastructure + ) { + private var nodePlans: List = listOf(1, 2).map { JiraNodePlan.Builder().build() } +// TODO private var instanceHooks: PreInstanceHooks = +// PreInstanceHooks(listOf(1..2).map { PreInstallHooks.default() }) // TODO two lists in sync? gotta be a better way // -// class Builder( -// private var jiraNode: TcpServer -// ) { -// private var hooks: PreInstallHooks = PreInstallHooks.default() -// private var installation: JiraInstallation = HookedJiraInstallation( -// ParallelInstallation( -// EmptyJiraHome(), -// PublicJiraSoftwareDistribution("7.13.0"), -// OracleJDK() -// ), -// hooks -// ) -// private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) -// -// fun jiraNode(jiraNode: TcpServer) = apply { this.jiraNode = jiraNode } -// fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation -// fun installation(installation: JiraInstallation) = apply { this.installation = installation } -// fun start(start: JiraStart) = apply { this.start = start } -// -// fun build() = JiraDataCenterPlan( -// jiraNode = jiraNode, -// hooks = hooks, -// installation = installation, -// start = start -// ) -// } +// fun build(): Supplier = JiraDataCenterPlan(nodePlans, infrastructure) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt index 8d2f4e3c..173b48ac 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt @@ -1,7 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import java.net.URI interface JiraInstance { val address: URI + val nodes: List } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt new file mode 100644 index 00000000..2b80ac64 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt @@ -0,0 +1,8 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports + +interface JiraInstancePlan { + fun materialize(): JiraInstance + fun report(): Reports +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 7d1ad934..1640a6ba 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -1,64 +1,49 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution -import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome -import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript -import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart -import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK import java.net.URI -import java.util.function.Supplier class JiraServerPlan private constructor( + private val plan: JiraNodePlan, private val infrastructure: Infrastructure, - val hooks: PreInstallHooks, - val installation: JiraInstallation, - val start: JiraStart -) : Supplier { + private val hooks: PreInstanceHooks +) : JiraInstancePlan { - override fun get(): JiraServer { + private val reports: Reports = Reports() + + override fun materialize(): JiraInstance { + val nodeHooks = listOf(plan).map { it.hooks } + hooks.call(nodeHooks, reports) val jiraNode = infrastructure.serve(8080, "jira-node") - val installed = installation.install(jiraNode) - val started = start.start(installed) - return JiraServer(started) + val installed = plan.installation.install(jiraNode, reports) + val started = plan.start.start(installed, reports) + val instance = JiraServer(started) + hooks.postInstance.call(instance, reports) + return instance } - class JiraServer( - val node: StartedJira + override fun report(): Reports = reports.copy() + + private class JiraServer( + node: StartedJira ) : JiraInstance { override val address: URI = node.installed.host.run { URI("http://$ip:$publicPort/") } + override val nodes: List = listOf(node) } class Builder( private var infrastructure: Infrastructure ) { - private var hooks: PreInstallHooks = PreInstallHooks.default() - private var installation: JiraInstallation = HookedJiraInstallation( - ParallelInstallation( - EmptyJiraHome(), - PublicJiraSoftwareDistribution("7.13.0"), - OracleJDK() - ), - hooks - ) - private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) + private var plan: JiraNodePlan = JiraNodePlan.Builder().build() + private var hooks: PreInstanceHooks = PreInstanceHooks.default() + fun plan(plan: JiraNodePlan) = apply { this.plan = plan } fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } - fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation - fun installation(installation: JiraInstallation) = apply { this.installation = installation } - fun start(start: JiraStart) = apply { this.start = start } + fun hooks(hooks: PreInstanceHooks) = apply { this.hooks = hooks } - fun build() = JiraServerPlan( - infrastructure = infrastructure, - hooks = hooks, - installation = installation, - start = start - ) + fun build(): JiraInstancePlan = JiraServerPlan(plan, infrastructure, hooks) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt index 48dcb0f8..42e3442c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt @@ -1,15 +1,17 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance -import java.net.URI +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports interface PostInstanceHook { /** * @param [instance] a standalone Jira Server node or a Jira Data Center cluster - * @param [hooks] inserts future hooks and reports + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( - instance: URI, - hooks: PostInstanceHooks + instance: JiraInstance, + hooks: PostInstanceHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt index f519425e..b56147ae 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt @@ -1,13 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import java.net.URI +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import java.util.* import java.util.concurrent.ConcurrentLinkedQueue -class PostInstanceHooks( - val nodes: List -) { +class PostInstanceHooks private constructor() { private val hooks: Queue = ConcurrentLinkedQueue() @@ -15,12 +12,18 @@ class PostInstanceHooks( hooks.add(hook) } - fun call(instance: URI) { + fun call(instance: JiraInstance, reports: Reports) { while (true) { hooks .poll() - ?.call(instance, this) + ?.call(instance, this, reports) ?: break } } + + + companion object Factory { + fun default(): PostInstanceHooks = empty() + fun empty(): PostInstanceHooks = PostInstanceHooks() + } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt index 31c4c777..be674f40 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt @@ -1,11 +1,18 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports + interface PreInstanceHook { /** - * @param [hooks] inserts future hooks and reports + * @param [nodes] inserts node hooks + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( - hooks: PreInstanceHooks + nodes: List, + hooks: PreInstanceHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt index 238db71a..5643ca27 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt @@ -1,26 +1,31 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import java.util.* import java.util.concurrent.ConcurrentLinkedQueue -class PreInstanceHooks( - val nodes: List +class PreInstanceHooks private constructor( + val postInstance: PostInstanceHooks ) { private val hooks: Queue = ConcurrentLinkedQueue() - val postInstance = PostInstanceHooks(nodes) fun insert(hook: PreInstanceHook) { hooks.add(hook) } - fun call() { + internal fun call(nodes: List, reports: Reports) { while (true) { hooks .poll() - ?.call(this) + ?.call(nodes, this, reports) ?: break } } + + companion object Factory { + fun default(): PreInstanceHooks = PreInstanceHooks(PostInstanceHooks.default()) + fun empty(): PreInstanceHooks = PreInstanceHooks(PostInstanceHooks.empty()) + } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt index f0b0e746..d4664efe 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt @@ -5,43 +5,40 @@ import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK +import com.atlassian.performance.tools.infrastructure.jira.install.hook.HookedJiraInstallation +import com.atlassian.performance.tools.infrastructure.jira.start.hook.HookedJiraStart import net.jcip.annotations.NotThreadSafe class JiraNodePlan private constructor( - val hooks: PreInstallHooks, val installation: JiraInstallation, - val start: JiraStart + val start: JiraStart, + internal val hooks: PreInstallHooks ) { fun materialize(host: TcpHost) = JiraNode(host, this) @NotThreadSafe class Builder { - private var hooks: PreInstallHooks = PreInstallHooks.default() - private var installation: JiraInstallation = HookedJiraInstallation( - ParallelInstallation( - EmptyJiraHome(), - PublicJiraSoftwareDistribution("7.13.0"), - OracleJDK() - ), - hooks + private var installation: JiraInstallation = ParallelInstallation( + EmptyJiraHome(), + PublicJiraSoftwareDistribution("7.13.0"), + OracleJDK() ) - private var start: JiraStart = HookedJiraStart(JiraLaunchScript(), hooks.preStart) + private var start: JiraStart = JiraLaunchScript() + private var hooks: PreInstallHooks = PreInstallHooks.default() - fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } // TODO this doesn't affect the start or installation fun installation(installation: JiraInstallation) = apply { this.installation = installation } fun start(start: JiraStart) = apply { this.start = start } + fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } fun build() = JiraNodePlan( - hooks = hooks, - installation = installation, - start = start + HookedJiraInstallation(installation, hooks), + HookedJiraStart(start, hooks.preStart), + hooks ) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt index 75979fca..b23e5965 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/FileListing.kt @@ -9,8 +9,10 @@ class FileListing( override fun locate( ssh: SshConnection ): List = ssh - .execute("ls $pattern") - .output - .lines() - .filter { it.isNotBlank() } + .safeExecute("ls $pattern") + .takeIf { it.isSuccessful() } + ?.output + ?.lines() + ?.filter { it.isNotBlank() } + ?: emptyList() } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index bfc8b1cd..59a66270 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -1,18 +1,50 @@ package com.atlassian.performance.tools.infrastructure.api.jira.report +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.os.RemotePath +import com.atlassian.performance.tools.io.api.ensureDirectory +import com.atlassian.performance.tools.io.api.resolveSafely +import java.io.File +import java.nio.file.Path import java.util.* import java.util.concurrent.ConcurrentLinkedQueue -class Reports { - private val reports: Queue = ConcurrentLinkedQueue() +class Reports private constructor( + private val hostReports: Queue +) { + constructor() : this(ConcurrentLinkedQueue()) fun add( - report: Report + report: Report, + host: TcpHost ) { - reports.add(report) + hostReports.add(HostReport(host, report)) } - fun list(): Iterable { - return reports.toList() + fun downloadTo( + localDirectory: Path + ): File { + localDirectory.ensureDirectory() + hostReports.groupBy { it.host }.map { (host, reports) -> + host.ssh.newConnection().use { ssh -> + reports + .flatMap { report -> + report.report.locate(ssh).map { path -> RemotePath(host.ssh.host, path) } + } + .forEach { remotePath -> + remotePath.download(localDirectory.resolveSafely(host.name)) + } + } + } + return localDirectory.toFile() } + + fun copy(): Reports { + return Reports(ConcurrentLinkedQueue(hostReports)) + } + + private class HostReport( + val host: TcpHost, + val report: Report + ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt index 55e8ec6d..3ce78b6c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraLaunchScript.kt @@ -1,13 +1,15 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.Ssh import java.time.Duration class JiraLaunchScript : JiraStart { override fun start( - installed: InstalledJira + installed: InstalledJira, + reports: Reports ): StartedJira { val installation = installed.installation Ssh(installation.host).newConnection().use { ssh -> diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt index 9f2d9cd8..706e01e2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt @@ -1,12 +1,20 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import net.jcip.annotations.ThreadSafe @ThreadSafe interface JiraStart { + /** + * Starts the [installed] Jira. + * + * @param [installed] will start the Jira + * @param [reports] accumulates reports + */ fun start( - installed: InstalledJira + installed: InstalledJira, + reports: Reports ): StartedJira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt index 6bc2f30e..f6f35c5d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt @@ -1,12 +1,13 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing -import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection -class AccessLogs : PostStartHook { +class AccessLogs : PreStartHook { - override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { - hooks.reports.add(FileListing("${jira.installed.installation.path}/logs/*access*")) + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PreStartHooks, reports: Reports) { + reports.add(FileListing("${jira.installation.path}/logs/*access*"), jira.host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt index e4485af4..547e51af 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport import com.atlassian.performance.tools.ssh.api.SshConnection @@ -9,9 +10,10 @@ class JstatHook : PostStartHook { override fun call( ssh: SshConnection, jira: StartedJira, - hooks: PostStartHooks + hooks: PostStartHooks, + reports: Reports ) { val process = jira.installed.jdk.jstatMonitoring.start(ssh, jira.pid) - hooks.reports.add(RemoteMonitoringProcessReport(process)) + reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt index c3c47123..ee867e14 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.ssh.api.SshConnection @@ -11,11 +12,13 @@ interface PostStartHook { /** * @param [ssh] connects to the [jira] * @param [jira] points to the started Jira - * @param [hooks] inserts future reports + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( ssh: SshConnection, jira: StartedJira, - hooks: PostStartHooks + hooks: PostStartHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt index 21b0b46a..77671948 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt @@ -9,7 +9,6 @@ import java.util.concurrent.ConcurrentLinkedQueue class PostStartHooks private constructor() { private val hooks: Queue = ConcurrentLinkedQueue() - val reports = Reports() fun insert( hook: PostStartHook @@ -19,12 +18,13 @@ class PostStartHooks private constructor() { internal fun call( ssh: SshConnection, - jira: StartedJira + jira: StartedJira, + reports: Reports ) { while (true) { hooks .poll() - ?.call(ssh, jira, this) + ?.call(ssh, jira, this, reports) ?: break } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt index d0fa8326..0123305e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection /** @@ -11,11 +12,13 @@ interface PreStartHook { /** * @param [ssh] connects to the [jira] * @param [jira] points to the installed Jira - * @param [hooks] inserts future hooks and reports + * @param [hooks] inserts future hooks + * @param [reports] accumulates reports */ fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PreStartHooks + hooks: PreStartHooks, + reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt index 6ce16b42..bc3082f4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection import java.util.* import java.util.concurrent.ConcurrentLinkedQueue @@ -10,7 +11,6 @@ class PreStartHooks private constructor( ) { private val hooks: Queue = ConcurrentLinkedQueue() - val reports = postStart.reports fun insert( hook: PreStartHook @@ -20,18 +20,21 @@ class PreStartHooks private constructor( internal fun call( ssh: SshConnection, - jira: InstalledJira + jira: InstalledJira, + reports: Reports ) { while (true) { hooks .poll() - ?.call(ssh, jira, this) + ?.call(ssh, jira, this, reports) ?: break } } companion object Factory { - fun default() = PreStartHooks(PostStartHooks.default()) + fun default() = PreStartHooks(PostStartHooks.default()).apply { + insert(AccessLogs()) + } fun empty() = PreStartHooks(PostStartHooks.empty()) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index f1239d3a..1ea0c995 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jvm.ThreadDump import com.atlassian.performance.tools.ssh.api.SshConnection @@ -15,11 +16,11 @@ class RestUpgrade( private val adminPassword: String ) : PostStartHook { - override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks) { + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val threadDump = ThreadDump(jira.pid, jira.installed.jdk) val privatePort = jira.installed.host.privatePort val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$privatePort/rest/api/2/upgrade") - hooks.reports.add(FileListing("thread-dumps/*")) + reports.add(FileListing("thread-dumps/*"), jira.installed.host) waitForStatusToChange( statusQuo = "000", timeout = timeouts.offlineTimeout, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index c1dedea8..806b4556 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -44,7 +44,7 @@ internal object Mysql { .imageName("mysql:5.7.32") .pullTimeout(Duration.ofMinutes(5)) .parameters( - host?.let { "-p ${it.publicPort}:${it.privatePort}" } ?: "-p 3306:3306", + host?.let { "-p ${it.privatePort}:${it.publicPort}" } ?: "-p 3306:3306", "-v `realpath $dataDir`:/var/lib/mysql", *extraParameters ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClient.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClient.kt index 59bba7bb..cb5ad63a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClient.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClient.kt @@ -3,14 +3,18 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.ssh.api.SshConnection import java.io.File -internal class SshMysqlClient : SshSqlClient { +internal class SshMysqlClient( + private val address: String = "127.0.0.1", + private val port: Int = 3306, + private val user: String = "root" +) : SshSqlClient { override fun runSql( ssh: SshConnection, sql: String ): SshConnection.SshResult { val quotedSql = sql.quote('"') - return ssh.execute("mysql -h 127.0.0.1 -u root -e $quotedSql") + return ssh.execute("mysql -h $address -P $port -u $user -e $quotedSql") } override fun runSql( @@ -19,7 +23,7 @@ internal class SshMysqlClient : SshSqlClient { ): SshConnection.SshResult { val remoteSqlFile = sql.name ssh.upload(sql, remoteSqlFile) - val result = ssh.execute("mysql -h 127.0.0.1 -u root < $remoteSqlFile") + val result = ssh.execute("mysql -h $address -P $port -u $user < $remoteSqlFile") ssh.execute("rm $remoteSqlFile") return result } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt similarity index 56% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt index a7633b23..153fafe8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/HookedJiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt @@ -1,8 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports class HookedJiraInstallation( private val installation: JiraInstallation, @@ -10,14 +12,15 @@ class HookedJiraInstallation( ) : JiraInstallation { override fun install( - host: TcpHost + host: TcpHost, + reports: Reports ): InstalledJira { host.ssh.newConnection().use { ssh -> - hooks.call(ssh, host) + hooks.call(ssh, host, reports) } - val installed = installation.install(host) + val installed = installation.install(host, reports) host.ssh.newConnection().use { ssh -> - hooks.postInstall.call(ssh, installed) + hooks.postInstall.call(ssh, installed, reports) } return installed } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt index 5b26eaa1..294ab3e5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt @@ -3,6 +3,7 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks @@ -18,7 +19,7 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class ProfilerHook( private val profiler: Profiler ) : PostInstallHook { - override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks) { + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { profiler.install(ssh) hooks.preStart.postStart.insert(InstalledProfiler(profiler)) } @@ -31,11 +32,12 @@ private class InstalledProfiler( override fun call( ssh: SshConnection, jira: StartedJira, - hooks: PostStartHooks + hooks: PostStartHooks, + reports: Reports ) { val process = profiler.start(ssh, jira.pid) if (process != null) { - hooks.reports.add(RemoteMonitoringProcessReport(process)) + reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt index 78282a69..1e27f25b 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt @@ -1,8 +1,9 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.splunk.SplunkForwarder import com.atlassian.performance.tools.ssh.api.SshConnection @@ -13,7 +14,8 @@ internal class SplunkForwarderHook( override fun call( ssh: SshConnection, jira: InstalledJira, - hooks: PostInstallHooks + hooks: PostInstallHooks, + reports: Reports ) { splunk.jsonifyLog4j(ssh, "${jira.installation.path}/atlassian-jira/WEB-INF/classes/log4j.properties") splunk.run(ssh, jira.host.name, "/home/ubuntu/jirahome/log") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt similarity index 55% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt index 911c2b43..e23395f9 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/HookedJiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt @@ -1,8 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks class HookedJiraStart( private val start: JiraStart, @@ -10,14 +12,15 @@ class HookedJiraStart( ) : JiraStart { override fun start( - installed: InstalledJira + installed: InstalledJira, + reports: Reports ): StartedJira { installed.host.ssh.newConnection().use { ssh -> - hooks.call(ssh, installed) + hooks.call(ssh, installed, reports) } - val started = start.start(installed) + val started = start.start(installed, reports) installed.host.ssh.newConnection().use { ssh -> - hooks.postStart.call(ssh, started) + hooks.postStart.call(ssh, started, reports) } return started } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt new file mode 100644 index 00000000..f16f3d5a --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -0,0 +1,18 @@ +package com.atlassian.performance.tools.infrastructure + +import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage +import java.net.URI +import java.time.Duration + +class Datasets { + + fun smallJiraSeven() = URI("https://s3-eu-west-1.amazonaws.com/") + .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1sjxdtrv5hdhj/") + .resolve("dataset-f8dba866-9d1b-492e-b76c-f4a78ac3958c/") + .let { uri -> + HttpDatasetPackage( + uri = uri.resolve("database.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 019ead0e..c44225f7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -22,13 +22,14 @@ internal class DockerInfrastructure : Infrastructure { override fun serve(port: Int, name: String): TcpHost { val container = SshUbuntuContainer(Consumer { it.addExposedPort(port) + it.setPrivilegedMode(true) }) val sshUbuntu = container.start() allocatedResources.offer(sshUbuntu) return TcpHost( "localhost", - sshUbuntu.container.getMappedPort(port), port, + sshUbuntu.container.getMappedPort(port), name, sshUbuntu.toSsh() ) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt deleted file mode 100644 index 90a83eea..00000000 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HookedJiraStartIT.kt +++ /dev/null @@ -1,142 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install - -import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer -import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage -import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution -import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure -import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.HookedJiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraDataCenterPlan -import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraServerPlan -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan -import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.HookedJiraStart -import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK -import org.assertj.core.api.Assertions.assertThat -import org.junit.After -import org.junit.Before -import org.junit.Test -import java.net.URI -import java.nio.file.Files -import java.time.Duration -import java.util.* -import java.util.function.Supplier - -class HookedJiraStartIT { - - private lateinit var infrastructure: Infrastructure - - @Before - fun setUp() { - infrastructure = DockerInfrastructure() - } - - @After - fun tearDown() { - infrastructure.releaseResources() - } - - @Test - fun shouldStartJiraWithHooks() { - // given - val hooks = PreInstallHooks.default() - val installation = HookedJiraInstallation( - ParallelInstallation( - jiraHomeSource = EmptyJiraHome(), - productDistribution = PublicJiraSoftwareDistribution("7.13.0"), - jdk = AdoptOpenJDK() - ), - hooks - ) - val start = HookedJiraStart(JiraLaunchScript(), hooks.preStart) - - // when - val jiraServer = JiraServerPlan.Builder(infrastructure) - .installation(installation) - .start(start) - .hooks(hooks) - .build() - .get() - - val host = jiraServer.node.installed.host - val reports = host.ssh.newConnection().use { ssh -> - hooks.reports.list().flatMap { it.locate(ssh) } - } - - // then - val serverXml = jiraServer - .node - .installed - .installation - .resolve("conf/server.xml") - .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" - HttpDatasetPackage( - uri = uri.resolve("database.tar.bz2"), - downloadTimeout = Duration.ofMinutes(6) - ) - } - instanceHooks.insert(DockerMysqlServer.Builder(infrastructure, smallJiraSeven).build()) - val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) - - // when - val dataCenter = dcPlan.get() - val reports = dataCenter.nodes.ssh.newConnection().use { ssh -> - nodeHooks.reports.list().flatMap { it.locate(ssh) } - } - - // then - dataCenter.nodes.forEach { node -> - val installed = node.installed - val serverXml = installed - .installation - .resolve("conf/server.xml") - .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" + val installed = node.installed + val serverXml = installed + .installation + .resolve("conf/server.xml") + .download(Files.createTempFile("downloaded-config", ".xml")) + assertThat(serverXml.readText()).contains(" Date: Fri, 2 Apr 2021 14:35:18 +0200 Subject: [PATCH 11/73] Fix hooked MySQL start --- .../api/database/DockerMysqlServer.kt | 4 +- .../api/database/DockerPostgresServer.kt | 70 ------------------- .../api/database/MinimalMySqlDatabase.kt | 2 +- .../api/database/MySqlDatabase.kt | 2 +- .../api/database/MysqlConnector.kt | 2 +- .../api/jira/install/TcpHost.kt | 3 +- .../api/jira/instance/JiraServerPlan.kt | 2 +- .../api/jira/start/hook/RestUpgrade.kt | 4 +- .../tools/infrastructure/database/MySql.kt | 21 ++---- .../tools/infrastructure/Datasets.kt | 39 ++++++++--- .../api/DockerInfrastructure.kt | 2 +- .../jira/install/hook/PreInstallHooksTest.kt | 2 +- .../api/jira/instance/JiraDataCenterPlanIT.kt | 8 +-- .../api/jira/instance/JiraServerPlanIT.kt | 8 +-- 14 files changed, 57 insertions(+), 112 deletions(-) delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 08a21bab..263fdb3c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -45,8 +45,8 @@ class DockerMysqlServer private constructor( host = server ).run(ssh) Ubuntu().install(ssh, listOf("mysql-client")) - val client = SshMysqlClient("127.0.0.1", server.privatePort) - Mysql.awaitDatabase(ssh) + val client = SshMysqlClient("127.0.0.1", server.port) + Mysql.awaitDatabase(ssh, client) return client } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt deleted file mode 100644 index 572c1fd5..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerPostgresServer.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.api.database - -import com.atlassian.performance.tools.infrastructure.api.Infrastructure - -import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage -import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.ssh.api.SshConnection -import org.apache.logging.log4j.LogManager -import org.apache.logging.log4j.Logger -import java.time.Duration.ofMinutes -import java.time.Duration.ofSeconds - -class DockerPostgresServer private constructor( -private val infrastructure: Infrastructure, - private val source: DatasetPackage, - private val maxConnections: Int -) : PreInstanceHook { - - private val logger: Logger = LogManager.getLogger(this::class.java) - - override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { - - val server = infrastructure.serve(5432, "postgres") - server.ssh.newConnection().use { setup(it, server) } - nodes.forEach { node -> - node.postInstall.insert(DatabaseIpConfig(server.ip)) - } - } - - private fun setup(ssh: SshConnection, server: TcpHost) { - val data = source.download(ssh) - val containerName = DockerContainer.Builder() - .imageName("postgres:9.6.15") - .pullTimeout(ofMinutes(5)) - .parameters(with(server) {"-p $privatePort:$publicPort"}, "-v `realpath $data`:/${TODO("download and mount Postgres data")}") - .arguments("-c 'listen_addresses='*''", "-c 'max_connections=$maxConnections'") - .build() - .run(ssh) - Thread.sleep(ofSeconds(15).toMillis()) - ssh.execute("sudo docker exec -u postgres $containerName psql --command \"CREATE USER jira WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN PASSWORD 'jira';\"") - ssh.execute("sudo docker exec -u postgres $containerName createdb -E UNICODE -l C -T template0 -O jira jira") - /** - * TODO Check logs for the following entry - * `LOG: database system is ready to accept connections` - */ - Thread.sleep(ofSeconds(15).toMillis()) - } - - class Builder( - private var infrastructure: Infrastructure, - private var source: DatasetPackage - ) { - private var maxConnections: Int = 200 - - fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } - fun source(source: DatasetPackage) = apply { this.source = source } - fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } - - fun build(): DockerPostgresServer = DockerPostgresServer( - infrastructure, - source, - maxConnections - ) - } -} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabase.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabase.kt index c24c5a28..8ef841f4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabase.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabase.kt @@ -23,7 +23,7 @@ class MinimalMysqlDatabase private constructor( override fun start(jira: URI, ssh: SshConnection) { val client = Mysql.installClient(ssh) - Mysql.awaitDatabase(ssh) + Mysql.awaitDatabase(ssh, client) // Based on [jira docs](https://confluence.atlassian.com/adminjiraserver/connecting-jira-applications-to-mysql-5-7-966063305.html) client.runSql(ssh, "CREATE USER 'jiradbuser'@'%' IDENTIFIED BY '$jiraDbUserPassword';") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabase.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabase.kt index 34c37b40..40f3ad9a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabase.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabase.kt @@ -43,7 +43,7 @@ class MySqlDatabase( override fun start(jira: URI, ssh: SshConnection) { val client = Mysql.installClient(ssh) - Mysql.awaitDatabase(ssh) + Mysql.awaitDatabase(ssh, client) client.runSql(ssh, "UPDATE jiradb.propertystring SET propertyvalue = '$jira' WHERE id IN (select id from jiradb.propertyentry where property_key like '%baseurl%');") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt index 4aa5cd5b..b4a13348 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt @@ -26,6 +26,6 @@ class MysqlConnector : PostInstallHook { backoff = StaticBackoff(Duration.ofSeconds(5)) ) ssh.execute("tar -xzf mysql-connector-java-5.1.40.tar.gz") - ssh.execute("cp mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${jira.installation}/lib") + ssh.execute("cp mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${jira.installation.path}/lib") } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt index 83b3df2f..8fef4548 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt @@ -7,8 +7,7 @@ import com.atlassian.performance.tools.ssh.api.Ssh */ class TcpHost( val ip: String, - val publicPort: Int, - val privatePort: Int, + val port: Int, val name: String, val ssh: Ssh ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 1640a6ba..250c4f55 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -30,7 +30,7 @@ class JiraServerPlan private constructor( private class JiraServer( node: StartedJira ) : JiraInstance { - override val address: URI = node.installed.host.run { URI("http://$ip:$publicPort/") } + override val address: URI = node.installed.host.run { URI("http://$ip:$port/") } override val nodes: List = listOf(node) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index 1ea0c995..6cff1183 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -18,8 +18,8 @@ class RestUpgrade( override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val threadDump = ThreadDump(jira.pid, jira.installed.jdk) - val privatePort = jira.installed.host.privatePort - val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$privatePort/rest/api/2/upgrade") + val port = jira.installed.host.port + val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$port/rest/api/2/upgrade") reports.add(FileListing("thread-dumps/*"), jira.installed.host) waitForStatusToChange( statusQuo = "000", diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index 806b4556..23cbd9c0 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -3,14 +3,13 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction +import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection -import org.apache.logging.log4j.LogManager -import org.apache.logging.log4j.Logger import java.time.Duration -import java.time.Instant +import java.time.Duration.ofSeconds internal object Mysql { - private val logger: Logger = LogManager.getLogger(this::class.java) private val ubuntu = Ubuntu() /** @@ -44,7 +43,7 @@ internal object Mysql { .imageName("mysql:5.7.32") .pullTimeout(Duration.ofMinutes(5)) .parameters( - host?.let { "-p ${it.privatePort}:${it.publicPort}" } ?: "-p 3306:3306", + host?.port?.let { "-p $it:$it" } ?: "-p 3306:3306", "-v `realpath $dataDir`:/var/lib/mysql", *extraParameters ) @@ -54,14 +53,8 @@ internal object Mysql { ) .build() - fun awaitDatabase(ssh: SshConnection) { - val mysqlStart = Instant.now() - while (!ssh.safeExecute("mysql -h 127.0.0.1 -u root -e 'select 1;'").isSuccessful()) { - if (Instant.now() > mysqlStart + Duration.ofMinutes(15)) { - throw RuntimeException("MySQL didn't start in time") - } - logger.debug("Waiting for MySQL...") - Thread.sleep(Duration.ofSeconds(10).toMillis()) - } + fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient) { + IdempotentAction("wait for MySQL start") { sqlClient.runSql(ssh, "select 1;") } + .retry(90, StaticBackoff(ofSeconds(10))) } } \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index f16f3d5a..3f3601ed 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -1,18 +1,41 @@ package com.atlassian.performance.tools.infrastructure +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage +import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.RestUpgrade import java.net.URI import java.time.Duration class Datasets { - fun smallJiraSeven() = URI("https://s3-eu-west-1.amazonaws.com/") - .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1sjxdtrv5hdhj/") - .resolve("dataset-f8dba866-9d1b-492e-b76c-f4a78ac3958c/") - .let { uri -> - HttpDatasetPackage( - uri = uri.resolve("database.tar.bz2"), - downloadTimeout = Duration.ofMinutes(6) - ) + object JiraSevenDataset { + private val s3Bucket = URI("https://s3-eu-west-1.amazonaws.com/") + .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1sjxdtrv5hdhj/") + .resolve("dataset-f8dba866-9d1b-492e-b76c-f4a78ac3958c/") + + private val mysql = HttpDatasetPackage( + uri = s3Bucket.resolve("database.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) + + val jiraHome = HttpDatasetPackage( + uri = s3Bucket.resolve("jirahome.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) + + fun hookMysql( + preInstanceHooks: PreInstanceHooks, + postStartHooks: PostStartHooks, + infrastructure: Infrastructure + ) { + val mysqlServer = DockerMysqlServer.Builder(infrastructure, mysql).build() + preInstanceHooks.insert(mysqlServer) + val dataUpgrade = RestUpgrade(JiraLaunchTimeouts.Builder().build(), "admin", "admin") + postStartHooks.insert(dataUpgrade) } + } } \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index c44225f7..0e7bde15 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -22,6 +22,7 @@ internal class DockerInfrastructure : Infrastructure { override fun serve(port: Int, name: String): TcpHost { val container = SshUbuntuContainer(Consumer { it.addExposedPort(port) + it.setPortBindings(listOf("$port:$port")) it.setPrivilegedMode(true) }) val sshUbuntu = container.start() @@ -29,7 +30,6 @@ internal class DockerInfrastructure : Infrastructure { return TcpHost( "localhost", port, - sshUbuntu.container.getMappedPort(port), name, sshUbuntu.toSsh() ) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index aba5e0ce..aeb25f99 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -13,7 +13,7 @@ import java.nio.file.Paths class PreInstallHooksTest { private val dummySsh = Ssh(SshHost("localhost", "dummyUser", Paths.get("dummyKey"))) - private val dummyServer = TcpHost("doesn't matter", 123, 123, "fake-server", dummySsh) + private val dummyServer = TcpHost("doesn't matter", 123, "fake-server", dummySsh) @Test fun shouldInsertDuringListing() { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index bc04ccfa..99698e7d 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -5,7 +5,7 @@ import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution -import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan @@ -39,7 +39,7 @@ class JiraDataCenterPlanIT { JiraNodePlan.Builder() .installation( ParallelInstallation( - jiraHomeSource = EmptyJiraHome(), + jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome), productDistribution = PublicJiraSoftwareDistribution("7.13.0"), jdk = AdoptOpenJDK() ) @@ -50,7 +50,7 @@ class JiraDataCenterPlanIT { } val instanceHooks = PreInstanceHooks.default().also { // TODO this plus `EmptyJiraHome()` = failing `DatabaseIpConfig` - couple them together or stop expecting a preexisting `dbconfig.xml`? but then what about missing lucene indexes? - it.insert(DockerMysqlServer.Builder(infrastructure, Datasets().smallJiraSeven()).build()) + it.insert(DockerMysqlServer.Builder(infrastructure, Datasets.JiraSevenDataset.mysql).build()) } val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) @@ -65,7 +65,7 @@ class JiraDataCenterPlanIT { .installation .resolve("conf/server.xml") .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" Date: Fri, 2 Apr 2021 14:35:33 +0200 Subject: [PATCH 12/73] Fix downloaded reports overwriting each other --- .../infrastructure/api/jira/install/hook/SystemLog.kt | 4 ++-- .../tools/infrastructure/api/jira/report/Reports.kt | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt index b3a50fd4..235e41d2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt @@ -1,13 +1,13 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection class SystemLog : PreInstallHook { override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks, reports: Reports) { - reports.add(StaticReport("/var/log/syslog"), host) + reports.add(FileListing("/var/log/syslog"), host) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index 59a66270..1a579e41 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -6,6 +6,7 @@ import com.atlassian.performance.tools.io.api.ensureDirectory import com.atlassian.performance.tools.io.api.resolveSafely import java.io.File import java.nio.file.Path +import java.nio.file.Paths import java.util.* import java.util.concurrent.ConcurrentLinkedQueue @@ -27,18 +28,26 @@ class Reports private constructor( localDirectory.ensureDirectory() hostReports.groupBy { it.host }.map { (host, reports) -> host.ssh.newConnection().use { ssh -> + val remoteBase = RemotePath(ssh.getHost(), ssh.execute("pwd").output.trim()) reports .flatMap { report -> report.report.locate(ssh).map { path -> RemotePath(host.ssh.host, path) } } .forEach { remotePath -> - remotePath.download(localDirectory.resolveSafely(host.name)) + localDirectory + .resolveSafely(host.name) + .resolve(remoteBase.toLocalRelativePath()) + .resolve(remotePath.toLocalRelativePath()) + .normalize() + .let { remotePath.download(it) } } } } return localDirectory.toFile() } + private fun RemotePath.toLocalRelativePath(): Path = Paths.get(path.trimStart('/')) + fun copy(): Reports { return Reports(ConcurrentLinkedQueue(hostReports)) } From c39618a475d8060f6cc9fcec9c764eb036ead4c2 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 2 Apr 2021 15:25:19 +0200 Subject: [PATCH 13/73] fixup: Fix hooked MySQL start --- .../performance/tools/infrastructure/Datasets.kt | 14 ++++++++------ .../api/jira/instance/JiraDataCenterPlanIT.kt | 8 +++----- .../api/jira/instance/JiraServerPlanIT.kt | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 3f3601ed..5c475ff2 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -27,14 +27,16 @@ class Datasets { downloadTimeout = Duration.ofMinutes(6) ) - fun hookMysql( - preInstanceHooks: PreInstanceHooks, - postStartHooks: PostStartHooks, - infrastructure: Infrastructure - ) { + fun hookMysql(preInstanceHooks: PreInstanceHooks, infrastructure: Infrastructure) { val mysqlServer = DockerMysqlServer.Builder(infrastructure, mysql).build() preInstanceHooks.insert(mysqlServer) - val dataUpgrade = RestUpgrade(JiraLaunchTimeouts.Builder().build(), "admin", "admin") + } + + fun hookMysql(postStartHooks: PostStartHooks) { + val timeouts = JiraLaunchTimeouts.Builder() + .initTimeout(Duration.ofSeconds(30)) + .build() + val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") postStartHooks.insert(dataUpgrade) } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 99698e7d..21fc7f8c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -3,7 +3,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.Datasets import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation @@ -45,13 +44,12 @@ class JiraDataCenterPlanIT { ) ) .start(JiraLaunchScript()) - .hooks(PreInstallHooks.default()) + .hooks(PreInstallHooks.default().also { Datasets.JiraSevenDataset.hookMysql(it.postStart) }) .build() } - val instanceHooks = PreInstanceHooks.default().also { + val instanceHooks = PreInstanceHooks.default() // TODO this plus `EmptyJiraHome()` = failing `DatabaseIpConfig` - couple them together or stop expecting a preexisting `dbconfig.xml`? but then what about missing lucene indexes? - it.insert(DockerMysqlServer.Builder(infrastructure, Datasets.JiraSevenDataset.mysql).build()) - } + .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) try { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index fb17f464..584528d1 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -3,7 +3,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.Datasets import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation @@ -35,6 +34,7 @@ class JiraServerPlanIT { fun shouldStartJiraWithHooks() { // given val hooks = PreInstallHooks.default() + .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } val nodePlan = JiraNodePlan.Builder() .hooks(hooks) .installation( @@ -48,7 +48,7 @@ class JiraServerPlanIT { .hooks(hooks) .build() val instanceHooks = PreInstanceHooks.default() - .also { it.insert(DockerMysqlServer.Builder(infrastructure, Datasets.JiraSevenDataset.mysql).build()) } + .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } val jiraServerPlan = JiraServerPlan.Builder(infrastructure) .plan(nodePlan) .hooks(instanceHooks) From 723f465c9a419e318a11b766d439b8583cb948c9 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 2 Apr 2021 15:26:35 +0200 Subject: [PATCH 14/73] Make `Infrastructure` `AutoCloseable` --- .../performance/tools/infrastructure/api/Infrastructure.kt | 3 +-- .../tools/infrastructure/api/DockerInfrastructure.kt | 4 ++-- .../infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt | 2 +- .../infrastructure/api/jira/instance/JiraServerPlanIT.kt | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt index 219d74e4..de596b36 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -4,8 +4,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan -interface Infrastructure { +interface Infrastructure : AutoCloseable { fun serve(jiraNodePlans: List): List fun serve(port: Int, name: String): TcpHost - fun releaseResources() } \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 0e7bde15..34ea1563 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -26,7 +26,7 @@ internal class DockerInfrastructure : Infrastructure { it.setPrivilegedMode(true) }) val sshUbuntu = container.start() - allocatedResources.offer(sshUbuntu) + allocatedResources.add(sshUbuntu) return TcpHost( "localhost", port, @@ -35,7 +35,7 @@ internal class DockerInfrastructure : Infrastructure { ) } - override fun releaseResources() { + override fun close() { while (true) { allocatedResources .poll() diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 21fc7f8c..903913e7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -28,7 +28,7 @@ class JiraDataCenterPlanIT { @After fun tearDown() { - infrastructure.releaseResources() + infrastructure.close() } @Test diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 584528d1..fdb80901 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -27,7 +27,7 @@ class JiraServerPlanIT { @After fun tearDown() { - infrastructure.releaseResources() + infrastructure.close() } @Test From abc3bd2ecd19b172cf2349e2bdf0489df2ac9415 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 9 Apr 2021 12:44:54 +0200 Subject: [PATCH 15/73] Fix MySQL unit tests --- .../infrastructure/api/database/LicenseOverridingMysqlTest.kt | 4 ++-- .../tools/infrastructure/database/SshMysqlClientTest.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/LicenseOverridingMysqlTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/LicenseOverridingMysqlTest.kt index b03f9f7a..69468123 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/LicenseOverridingMysqlTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/LicenseOverridingMysqlTest.kt @@ -113,13 +113,13 @@ class LicenseOverridingMysqlTest { private fun generateExpectedCommands(ssh: RememberingSshConnection): List { return listOf( // essentially, delete all existing licences - """mysql -h 127.0.0.1 -u root -e "DELETE FROM jiradb.productlicense;"""", + """mysql -h 127.0.0.1 -P 3306 -u root -e "DELETE FROM jiradb.productlicense;"""", // then import the new ones *ssh.uploads .map { listOf( - """mysql -h 127.0.0.1 -u root < ${it.remoteDestination}""", + """mysql -h 127.0.0.1 -P 3306 -u root < ${it.remoteDestination}""", """rm ${it.remoteDestination}""" ) } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClientTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClientTest.kt index 2773e309..92c9261d 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClientTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/database/SshMysqlClientTest.kt @@ -20,7 +20,7 @@ class SshMysqlClientTest { assertThat(ssh.commands) .`as`("SSH commands") .containsExactly( - "mysql -h 127.0.0.1 -u root -e \"$command\"" + "mysql -h 127.0.0.1 -P 3306 -u root -e \"$command\"" ) } @@ -36,7 +36,7 @@ class SshMysqlClientTest { assertThat(ssh.commands) .`as`("SSH commands") .containsExactly( - "mysql -h 127.0.0.1 -u root < ${file.name}", + "mysql -h 127.0.0.1 -P 3306 -u root < ${file.name}", "rm ${file.name}" ) } From c95a6579a9f01d4acb5b35983b09f37e3587dbe5 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 9 Apr 2021 12:55:19 +0200 Subject: [PATCH 16/73] Update dependency locks --- build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 14cd364d..c36713f5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -76,7 +76,8 @@ fun webdriver(): List = listOf( "selenium-support", "selenium-chrome-driver" ).map { module -> - "org.seleniumhq.selenium:$module:3.141.59" + "org.seleniumhq.selenium:$module:[3.11.0, 3.999.999]" + // it's not `4.0.0)`, because their release channel is polluted with unstable versions like 4.0.0-alpha-1 } fun log4j( From 266762581fa2afe223e7aab150232f49a4fd9a32 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 9 Apr 2021 17:13:24 +0200 Subject: [PATCH 17/73] Test on `docker-java` --- build.gradle.kts | 8 + .../apiDependenciesMetadata.lockfile | 8 +- .../compileClasspath.lockfile | 8 +- gradle/dependency-locks/default.lockfile | 8 +- ...mplementationDependenciesMetadata.lockfile | 8 +- .../runtimeClasspath.lockfile | 8 +- .../testApiDependenciesMetadata.lockfile | 9 +- gradle/dependency-locks/testCompile.lockfile | 9 +- .../testCompileClasspath.lockfile | 11 +- ...mplementationDependenciesMetadata.lockfile | 11 +- gradle/dependency-locks/testRuntime.lockfile | 9 +- .../testRuntimeClasspath.lockfile | 11 +- .../api/database/DockerMysqlServer.kt | 2 +- .../api/jira/install/TcpHost.kt | 3 +- .../api/jira/install/hook/JvmConfig.kt | 2 +- .../api/jira/instance/JiraServerPlan.kt | 2 +- .../infrastructure/api/jvm/AdoptOpenJDK.kt | 2 + .../infrastructure/api/jvm/AdoptOpenJDK11.kt | 2 + .../tools/infrastructure/api/jvm/OracleJDK.kt | 2 + .../tools/infrastructure/DockerIT.kt | 34 ++--- .../infrastructure/SshUbuntuExtensions.kt | 14 -- .../api/DockerInfrastructure.kt | 137 +++++++++++++++--- .../infrastructure/api/browser/ChromeIT.kt | 8 +- .../api/browser/chromium/Chromium69IT.kt | 7 +- .../chromium/PageLoadTimeoutRecoveryTest.kt | 7 +- .../api/database/MinimalMySqlDatabaseIT.kt | 20 +-- .../api/database/MySqlDatabaseIT.kt | 18 +-- .../api/dataset/HttpDatasetPackageIT.kt | 7 +- .../PublicJiraServiceDeskDistributionIT.kt | 11 +- .../PublicJiraSoftwareDistributionsIT.kt | 15 +- .../jira/install/hook/PreInstallHooksTest.kt | 2 +- .../infrastructure/api/jvm/JdkSupport.kt | 7 +- .../infrastructure/api/jvm/JstatSupport.kt | 9 +- .../infrastructure/api/jvm/ThreadDumpIT.kt | 7 +- .../tools/infrastructure/api/os/UbuntuIT.kt | 18 ++- .../api/profiler/AsyncProfilerIT.kt | 41 ++---- .../lib/docker/ConnectedContainer.kt | 30 ++++ .../lib/docker/CreatedContainer.kt | 18 +++ .../lib/docker/DockerNetwork.kt | 18 +++ .../lib/docker/StartedContainer.kt | 23 +++ 40 files changed, 375 insertions(+), 199 deletions(-) delete mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshUbuntuExtensions.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/ConnectedContainer.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/CreatedContainer.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/DockerNetwork.kt create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/StartedContainer.kt diff --git a/build.gradle.kts b/build.gradle.kts index c36713f5..fba3fe7f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,10 +33,16 @@ configurations.all { "org.jetbrains:annotations" -> useVersion("15.0") "com.google.code.findbugs:jsr305" -> useVersion("3.0.2") "org.apache.commons:commons-compress" -> useVersion("1.9") + "commons-io:commons-io" -> useVersion("2.6") + "org.apache.commons:commons-lang3" -> useVersion("3.12.0") } when (requested.group) { "org.jetbrains.kotlin" -> useVersion(kotlinVersion) "org.apache.logging.log4j" -> useVersion(log4jVersion) + "org.bouncycastle" -> useVersion("1.64") + // Gradle 5 treats this module as conflicted, even though the range is compatible + // perhaps Gradle 6 will handle it better + "com.github.docker-java" -> useVersion("3.2.13") } } @@ -70,6 +76,8 @@ dependencies { testCompile("com.atlassian.performance.tools:ssh-ubuntu:0.3.0") testCompile("org.rnorth.duct-tape:duct-tape:1.0.8") testCompile("org.threeten:threeten-extra:1.5.0") + testCompile("com.github.docker-java:docker-java-core:[3.2.5, 4.0.0)") + testCompile("com.github.docker-java:docker-java-transport-zerodep:[3.2.5, 4.0.0)") } fun webdriver(): List = listOf( diff --git a/gradle/dependency-locks/apiDependenciesMetadata.lockfile b/gradle/dependency-locks/apiDependenciesMetadata.lockfile index a9a97519..d04bdf03 100644 --- a/gradle/dependency-locks/apiDependenciesMetadata.lockfile +++ b/gradle/dependency-locks/apiDependenciesMetadata.lockfile @@ -23,7 +23,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 net.bytebuddy:byte-buddy:1.8.15 @@ -31,7 +31,7 @@ net.i2p.crypto:eddsa:0.2.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -39,8 +39,8 @@ org.apache.logging.log4j:log4j-api:2.17.2 org.apache.logging.log4j:log4j-core:2.17.2 org.apache.logging.log4j:log4j-jul:2.17.2 org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.glassfish:javax.json:1.1 diff --git a/gradle/dependency-locks/compileClasspath.lockfile b/gradle/dependency-locks/compileClasspath.lockfile index feadccbc..defb2400 100644 --- a/gradle/dependency-locks/compileClasspath.lockfile +++ b/gradle/dependency-locks/compileClasspath.lockfile @@ -18,14 +18,14 @@ com.jcraft:jzlib:1.1.3 com.squareup.okhttp3:okhttp:3.11.0 com.squareup.okio:okio:1.14.0 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 javax.inject:javax.inject:1 javax.json:javax.json-api:1.1 net.bytebuddy:byte-buddy:1.8.15 net.i2p.crypto:eddsa:0.2.0 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 org.apache.logging.log4j:log4j-api:2.17.2 @@ -49,8 +49,8 @@ org.apache.maven:maven-repository-metadata:3.5.2 org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/default.lockfile b/gradle/dependency-locks/default.lockfile index b4b93fcf..9b6b1577 100644 --- a/gradle/dependency-locks/default.lockfile +++ b/gradle/dependency-locks/default.lockfile @@ -23,7 +23,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 javax.inject:javax.inject:1 @@ -33,7 +33,7 @@ net.i2p.crypto:eddsa:0.2.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -59,8 +59,8 @@ org.apache.maven:maven-repository-metadata:3.5.2 org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/implementationDependenciesMetadata.lockfile b/gradle/dependency-locks/implementationDependenciesMetadata.lockfile index b4b93fcf..9b6b1577 100644 --- a/gradle/dependency-locks/implementationDependenciesMetadata.lockfile +++ b/gradle/dependency-locks/implementationDependenciesMetadata.lockfile @@ -23,7 +23,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 javax.inject:javax.inject:1 @@ -33,7 +33,7 @@ net.i2p.crypto:eddsa:0.2.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -59,8 +59,8 @@ org.apache.maven:maven-repository-metadata:3.5.2 org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/runtimeClasspath.lockfile b/gradle/dependency-locks/runtimeClasspath.lockfile index b4b93fcf..9b6b1577 100644 --- a/gradle/dependency-locks/runtimeClasspath.lockfile +++ b/gradle/dependency-locks/runtimeClasspath.lockfile @@ -23,7 +23,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 javax.inject:javax.inject:1 @@ -33,7 +33,7 @@ net.i2p.crypto:eddsa:0.2.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -59,8 +59,8 @@ org.apache.maven:maven-repository-metadata:3.5.2 org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/testApiDependenciesMetadata.lockfile b/gradle/dependency-locks/testApiDependenciesMetadata.lockfile index d8a54931..c8dd00f5 100644 --- a/gradle/dependency-locks/testApiDependenciesMetadata.lockfile +++ b/gradle/dependency-locks/testApiDependenciesMetadata.lockfile @@ -10,7 +10,10 @@ com.atlassian.performance.tools:ssh-ubuntu:0.3.0 com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -22,20 +25,22 @@ com.hierynomus:sshj:0.23.0 com.jcraft:jzlib:1.1.3 com.squareup.okhttp3:okhttp:3.11.0 com.squareup.okio:okio:1.14.0 +commons-io:commons-io:2.6 junit:junit:4.13.2 net.bytebuddy:byte-buddy:1.8.15 net.i2p.crypto:eddsa:0.2.0 net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-exec:1.3 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.logging.log4j:log4j-api:2.17.2 org.apache.logging.log4j:log4j-core:2.17.2 org.apache.logging.log4j:log4j-jul:2.17.2 org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.glassfish:javax.json:1.1 diff --git a/gradle/dependency-locks/testCompile.lockfile b/gradle/dependency-locks/testCompile.lockfile index d8a54931..c8dd00f5 100644 --- a/gradle/dependency-locks/testCompile.lockfile +++ b/gradle/dependency-locks/testCompile.lockfile @@ -10,7 +10,10 @@ com.atlassian.performance.tools:ssh-ubuntu:0.3.0 com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -22,20 +25,22 @@ com.hierynomus:sshj:0.23.0 com.jcraft:jzlib:1.1.3 com.squareup.okhttp3:okhttp:3.11.0 com.squareup.okio:okio:1.14.0 +commons-io:commons-io:2.6 junit:junit:4.13.2 net.bytebuddy:byte-buddy:1.8.15 net.i2p.crypto:eddsa:0.2.0 net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-exec:1.3 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.logging.log4j:log4j-api:2.17.2 org.apache.logging.log4j:log4j-core:2.17.2 org.apache.logging.log4j:log4j-jul:2.17.2 org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.glassfish:javax.json:1.1 diff --git a/gradle/dependency-locks/testCompileClasspath.lockfile b/gradle/dependency-locks/testCompileClasspath.lockfile index ba80cded..bd533a68 100644 --- a/gradle/dependency-locks/testCompileClasspath.lockfile +++ b/gradle/dependency-locks/testCompileClasspath.lockfile @@ -11,7 +11,10 @@ com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance.tools:virtual-users:3.14.1 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -24,7 +27,7 @@ com.jcraft:jzlib:1.1.3 com.squareup.okhttp3:okhttp:3.11.0 com.squareup.okio:okio:1.14.0 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 javax.inject:javax.inject:1 javax.json:javax.json-api:1.1 @@ -34,7 +37,7 @@ net.i2p.crypto:eddsa:0.2.0 net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 org.apache.logging.log4j:log4j-api:2.17.2 @@ -59,8 +62,8 @@ org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/testImplementationDependenciesMetadata.lockfile b/gradle/dependency-locks/testImplementationDependenciesMetadata.lockfile index 2d726e03..414fb3e6 100644 --- a/gradle/dependency-locks/testImplementationDependenciesMetadata.lockfile +++ b/gradle/dependency-locks/testImplementationDependenciesMetadata.lockfile @@ -12,7 +12,10 @@ com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance.tools:virtual-users:3.14.1 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -28,7 +31,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 javax.inject:javax.inject:1 @@ -40,7 +43,7 @@ net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -67,8 +70,8 @@ org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/gradle/dependency-locks/testRuntime.lockfile b/gradle/dependency-locks/testRuntime.lockfile index d8a54931..c8dd00f5 100644 --- a/gradle/dependency-locks/testRuntime.lockfile +++ b/gradle/dependency-locks/testRuntime.lockfile @@ -10,7 +10,10 @@ com.atlassian.performance.tools:ssh-ubuntu:0.3.0 com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -22,20 +25,22 @@ com.hierynomus:sshj:0.23.0 com.jcraft:jzlib:1.1.3 com.squareup.okhttp3:okhttp:3.11.0 com.squareup.okio:okio:1.14.0 +commons-io:commons-io:2.6 junit:junit:4.13.2 net.bytebuddy:byte-buddy:1.8.15 net.i2p.crypto:eddsa:0.2.0 net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-exec:1.3 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.logging.log4j:log4j-api:2.17.2 org.apache.logging.log4j:log4j-core:2.17.2 org.apache.logging.log4j:log4j-jul:2.17.2 org.apache.logging.log4j:log4j-slf4j-impl:2.17.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.glassfish:javax.json:1.1 diff --git a/gradle/dependency-locks/testRuntimeClasspath.lockfile b/gradle/dependency-locks/testRuntimeClasspath.lockfile index 2d726e03..414fb3e6 100644 --- a/gradle/dependency-locks/testRuntimeClasspath.lockfile +++ b/gradle/dependency-locks/testRuntimeClasspath.lockfile @@ -12,7 +12,10 @@ com.atlassian.performance.tools:ssh:2.4.3 com.atlassian.performance.tools:virtual-users:3.14.1 com.atlassian.performance:selenium-js:1.0.1 com.fasterxml.jackson.core:jackson-annotations:2.10.3 +com.fasterxml.jackson.core:jackson-core:2.10.3 +com.fasterxml.jackson.core:jackson-databind:2.10.3 com.github.docker-java:docker-java-api:3.2.13 +com.github.docker-java:docker-java-core:3.2.13 com.github.docker-java:docker-java-transport-zerodep:3.2.13 com.github.docker-java:docker-java-transport:3.2.13 com.github.stephenc.jcip:jcip-annotations:1.0-1 @@ -28,7 +31,7 @@ com.squareup.okio:okio:1.14.0 com.typesafe:config:1.2.1 commons-cli:commons-cli:1.4 commons-codec:commons-codec:1.10 -commons-io:commons-io:2.5 +commons-io:commons-io:2.6 commons-logging:commons-logging:1.2 io.github.bonigarcia:webdrivermanager:1.7.1 javax.inject:javax.inject:1 @@ -40,7 +43,7 @@ net.java.dev.jna:jna:5.8.0 org.apache.commons:commons-compress:1.9 org.apache.commons:commons-csv:1.3 org.apache.commons:commons-exec:1.3 -org.apache.commons:commons-lang3:3.5 +org.apache.commons:commons-lang3:3.12.0 org.apache.commons:commons-math3:3.6.1 org.apache.httpcomponents:httpclient:4.5.5 org.apache.httpcomponents:httpcore:4.4.9 @@ -67,8 +70,8 @@ org.apache.maven:maven-resolver-provider:3.5.2 org.apache.maven:maven-settings-builder:3.5.2 org.apache.maven:maven-settings:3.5.2 org.assertj:assertj-core:3.11.1 -org.bouncycastle:bcpkix-jdk15on:1.56 -org.bouncycastle:bcprov-jdk15on:1.56 +org.bouncycastle:bcpkix-jdk15on:1.64 +org.bouncycastle:bcprov-jdk15on:1.64 org.checkerframework:checker-compat-qual:2.0.0 org.codehaus.mojo:animal-sniffer-annotations:1.14 org.codehaus.plexus:plexus-component-annotations:1.7.1 diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 263fdb3c..c746910c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -27,7 +27,7 @@ class DockerMysqlServer private constructor( val server = infrastructure.serve(3306, "mysql") val client = server.ssh.newConnection().use { setup(it, server) } nodes.forEach { node -> - node.postInstall.insert(DatabaseIpConfig(server.ip)) + node.postInstall.insert(DatabaseIpConfig(server.privateIp)) node.postInstall.insert(MysqlConnector()) } hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt index 8fef4548..75862d76 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt @@ -6,7 +6,8 @@ import com.atlassian.performance.tools.ssh.api.Ssh * Has open TCP sockets. */ class TcpHost( - val ip: String, + val publicIp: String, + val privateIp: String, val port: Int, val name: String, val ssh: Ssh diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt index 9fe8d5a7..88ed1e91 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt @@ -23,7 +23,7 @@ class JvmConfig( connection = ssh, config = config, gcLog = gcLog, - jiraIp = jira.host.ip + jiraIp = jira.host.publicIp ) val report = FileListing(gcLog.path("*")) reports.add(report, jira.host) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 250c4f55..322c0034 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -30,7 +30,7 @@ class JiraServerPlan private constructor( private class JiraServer( node: StartedJira ) : JiraInstance { - override val address: URI = node.installed.host.run { URI("http://$ip:$port/") } + override val address: URI = node.installed.host.run { URI("http://$publicIp:$port/") } override val nodes: List = listOf(node) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt index d853246f..f4a26119 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jvm +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.ssh.api.SshConnection @@ -30,6 +31,7 @@ class AdoptOpenJDK : VersionedJavaDevelopmentKit { override fun command(options: String) = "${jdkBin}java $options" private fun download(connection: SshConnection) { + Ubuntu().install(connection, listOf("curl")) IdempotentAction( description = "Download AdoptOpenJDK", action = { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt index 3975226b..0d567200 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jvm +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.ssh.api.SshConnection @@ -36,6 +37,7 @@ class AdoptOpenJDK11 : VersionedJavaDevelopmentKit { override fun command(options: String) = "${jdkBin}java $options" private fun download(connection: SshConnection) { + Ubuntu().install(connection, listOf("curl")) IdempotentAction( description = "Download AdoptOpenJDK", action = { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt index 1730539b..2800c926 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jvm +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.ssh.api.SshConnection import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger @@ -36,6 +37,7 @@ class OracleJDK : VersionedJavaDevelopmentKit { override fun command(options: String) = "${jreBin}java $options" private fun download(connection: SshConnection) { + Ubuntu().install(connection, listOf("curl")) val attempts = 0..3 for (attempt in attempts) { try { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/DockerIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/DockerIT.kt index e0d7189f..32520f07 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/DockerIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/DockerIT.kt @@ -1,5 +1,6 @@ package com.atlassian.performance.tools.infrastructure +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.junit.Test @@ -26,32 +27,23 @@ class DockerIT { } private fun testDockerInstall(version: String) { - SshUbuntuContainer.Builder() - .enableDocker() - .version(version) - .build() - .start() - .use { ubuntu -> - ubuntu.toSsh().newConnection().use { connection -> - DockerContainer.Builder() - .imageName("hello-world") - .build() - .run(connection) - } + DockerInfrastructure(version).use { infra -> + infra.serveSsh().newConnection().use { ssh -> + DockerContainer.Builder() + .imageName("hello-world") + .build() + .run(ssh) } + } } @Test fun shouldInstallIdempotently() { - SshUbuntuContainer.Builder() - .enableDocker() - .build() - .start() - .use { ubuntu -> - ubuntu.toSsh().newConnection().use { connection -> - Docker().install(connection) - Docker().install(connection) - } + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { ssh -> + Docker().install(ssh) + Docker().install(ssh) } + } } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshUbuntuExtensions.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshUbuntuExtensions.kt deleted file mode 100644 index 2de0c949..00000000 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshUbuntuExtensions.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.atlassian.performance.tools.infrastructure - -import com.atlassian.performance.tools.ssh.api.Ssh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntu -import java.time.Duration - -internal fun SshUbuntu.toSsh(): Ssh { - val ssh = Ssh(this.ssh) - ssh.newConnection().use { connection -> - connection.execute("apt-get update -qq", Duration.ofMinutes(3)) - connection.execute("export DEBIAN_FRONTEND=noninteractive; apt-get install sudo curl screen gnupg2 -y -qq", Duration.ofMinutes(10)) - } - return ssh -} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 34ea1563..74c3eca1 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -3,15 +3,40 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer +import com.atlassian.performance.tools.infrastructure.lib.docker.* +import com.atlassian.performance.tools.ssh.api.Ssh +import com.atlassian.performance.tools.ssh.api.SshHost +import com.atlassian.performance.tools.ssh.api.auth.PasswordAuthentication +import com.github.dockerjava.api.DockerClient +import com.github.dockerjava.api.command.PullImageResultCallback +import com.github.dockerjava.api.model.* +import com.github.dockerjava.core.DefaultDockerClientConfig +import com.github.dockerjava.core.DockerClientImpl +import com.github.dockerjava.zerodep.ZerodepDockerHttpClient +import java.time.Duration import java.util.* -import java.util.concurrent.ConcurrentLinkedQueue -import java.util.function.Consumer +import java.util.concurrent.ConcurrentLinkedDeque -internal class DockerInfrastructure : Infrastructure { +internal class DockerInfrastructure( + private val ubuntuVersion: String = "18.04" +) : Infrastructure { - private val allocatedResources: Queue = ConcurrentLinkedQueue() + private val allocatedResources: Deque = ConcurrentLinkedDeque() + private val docker: DockerClient + private val network: DockerNetwork + + + init { + val dockerConfig = DefaultDockerClientConfig.createDefaultConfigBuilder().build() + val dockerHttp = ZerodepDockerHttpClient.Builder().dockerHost(dockerConfig.dockerHost).build() + docker = DockerClientImpl.getInstance(dockerConfig, dockerHttp) + allocatedResources.add(docker) + network = docker + .createNetworkCmd() + .withName(UUID.randomUUID().toString()) + .execAsResource(docker) + allocatedResources.add(network) + } override fun serve(jiraNodePlans: List): List { return jiraNodePlans.mapIndexed { nodeIndex, plan -> @@ -19,26 +44,100 @@ internal class DockerInfrastructure : Infrastructure { } } + fun serveSsh(): Ssh = serve(888, "ssh").ssh + override fun serve(port: Int, name: String): TcpHost { - val container = SshUbuntuContainer(Consumer { - it.addExposedPort(port) - it.setPortBindings(listOf("$port:$port")) - it.setPrivilegedMode(true) - }) - val sshUbuntu = container.start() - allocatedResources.add(sshUbuntu) - return TcpHost( - "localhost", - port, - name, - sshUbuntu.toSsh() + docker + .pullImageCmd("rastasheep/ubuntu-sshd") + .withTag(ubuntuVersion) + .exec(PullImageResultCallback()) + .awaitCompletion() + val exposedPort = ExposedPort.tcp(port) + val dockerDaemonSocket = "/var/run/docker.sock" + val createdContainer = docker + .createContainerCmd("rastasheep/ubuntu-sshd:18.04") + .withHostConfig( + HostConfig() + .withPublishAllPorts(true) +// .withPrivileged(true) + .withBinds(Bind(dockerDaemonSocket, Volume(dockerDaemonSocket))) + ) + .withExposedPorts(exposedPort) + .withName(name + "-" + UUID.randomUUID()) + .execAsResource(docker) + allocatedResources.addLast(createdContainer) + return start(createdContainer, exposedPort) + } + + private fun start( + created: CreatedContainer, + port: ExposedPort + ): TcpHost { + val connectedContainer = docker + .connectToNetworkCmd() + .withContainerId(created.response.id) + .withNetworkId(network.response.id) + .execAsResource(docker) + allocatedResources.addLast(connectedContainer) + return start(connectedContainer, port) + } + + private fun start( + connected: ConnectedContainer, + port: ExposedPort + ): TcpHost { + val startedContainer = docker + .startContainerCmd(connected.containerId) + .execAsResource(docker) + allocatedResources.addLast(startedContainer); + return install(startedContainer, connected, port) + } + + private fun install( + started: StartedContainer, + connected: ConnectedContainer, + port: ExposedPort + ): TcpHost { + val networkSettings = docker + .inspectContainerCmd(started.id) + .exec() + .networkSettings + val ip = networkSettings + .networks + .values + .single { it.networkID == connected.networkId } + .ipAddress!! + val portBindings = networkSettings.ports.bindings + val sshPort = getHostPort(portBindings, ExposedPort.tcp(22)) + val tcpPort = getHostPort(portBindings, port) + val sshHost = SshHost( + ipAddress = "localhost", + userName = "root", + authentication = PasswordAuthentication("root"), + port = sshPort ) + val ssh = Ssh(sshHost) + ssh.newConnection().use { + it.execute("apt-get update", Duration.ofMinutes(2)) + it.execute("apt-get -y install sudo gnupg screen") + } + return TcpHost("localhost", ip, tcpPort, started.id, ssh) + } + + private fun getHostPort( + portBindings: MutableMap>, + port: ExposedPort + ): Int { + return portBindings[port]!! + .single() + .hostPortSpec + .toInt() } override fun close() { while (true) { allocatedResources - .poll() + .pollLast() ?.use {} ?: break } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt index c83b436f..788f38ab 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt @@ -1,8 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.browser -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.ssh.api.SshConnection -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.hamcrest.Matchers import org.junit.Assert import org.junit.Test @@ -11,8 +10,8 @@ class ChromeIT { @Test fun shouldInstallChromeBrowser() { - SshUbuntuContainer.Builder().build().start().use { ssh -> - ssh.toSsh().newConnection().use { connection -> + DockerInfrastructure().use { infra -> + infra.serve(80, "ChromeIT").ssh.newConnection().use { connection -> val wasInstalledBefore = isChromeInstalled(connection) Chrome().install(connection) @@ -23,7 +22,6 @@ class ChromeIT { Assert.assertThat(isInstalledAfter, Matchers.`is`(true)) Assert.assertThat(isChromeDriverInstalled(connection), Matchers.`is`(true)) } - } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/Chromium69IT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/Chromium69IT.kt index af1778de..02dd0f9c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/Chromium69IT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/Chromium69IT.kt @@ -1,10 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.browser.chromium -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.hamcrest.Matchers import org.junit.Assert import org.junit.Test @@ -14,8 +13,8 @@ class Chromium69IT { @Test fun shouldInstallBrowser() { - SshUbuntuContainer.Builder().build().start().use { sshUbuntu -> - sshUbuntu.toSsh().newConnection().use { connection -> + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { connection -> val installedBefore = isChromiumInstalled(connection) Chromium69().install(connection) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt index 960829ca..9699cfcb 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt @@ -1,10 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.browser.chromium +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.browser.Browser import com.atlassian.performance.tools.infrastructure.browser.SshChromium import com.atlassian.performance.tools.infrastructure.mock.MockHttpServer -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import com.sun.net.httpserver.HttpExchange import org.assertj.core.api.Assertions import org.openqa.selenium.TimeoutException @@ -20,8 +19,8 @@ internal class PageLoadTimeoutRecoveryTest { MockHttpServer().start().use { httpServer -> val fastResource = httpServer.register(FastResponse()) val slowResource = httpServer.register(SlowResponse()) - SshUbuntuContainer.Builder().build().start().use { sshUbuntu -> - val ssh = sshUbuntu.toSsh() + DockerInfrastructure().use { infra -> + val ssh = infra.serveSsh() ssh.forwardRemotePort(httpServer.getPort(), httpServer.getPort()).use { val localChromedriverPort = findFreePort() ssh.forwardLocalPort(localChromedriverPort, remoteChromedriverPort).use { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabaseIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabaseIT.kt index a50a8bce..0c082194 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabaseIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MinimalMySqlDatabaseIT.kt @@ -1,10 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.database -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import org.junit.Test import java.net.URI -import java.util.function.Consumer class MinimalMysqlDatabaseIT { @Test @@ -15,17 +13,13 @@ class MinimalMysqlDatabaseIT { .jiraDbUserPassword(password) .build() - SshUbuntuContainer.Builder() - .customization(Consumer { it.setPrivilegedMode(true) }) - .build() - .start() - .use { ubuntu -> - ubuntu.toSsh().newConnection().use { ssh -> - mysql.setup(ssh) - mysql.start(URI("https://dummy-jira.net"), ssh) + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { ssh-> + mysql.setup(ssh) + mysql.start(URI("https://dummy-jira.net"), ssh) - ssh.execute("mysql -h 127.0.0.1 -u $assumedUser -p$password -e 'USE jiradb; SHOW TABLES;'") - } + ssh.execute("mysql -h 127.0.0.1 -u $assumedUser -p$password -e 'USE jiradb; SHOW TABLES;'") } + } } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabaseIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabaseIT.kt index db3485eb..4b65fa23 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabaseIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MySqlDatabaseIT.kt @@ -1,12 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.database +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.junit.Test import java.net.URI import java.time.Duration -import java.util.function.Consumer /** * Note: We decided to use `Mysql` casing in this repository. Please don't repeat `MySql`. @@ -23,15 +21,11 @@ class MySqlDatabaseIT { ) val mysql = MySqlDatabase(databaseSource) - SshUbuntuContainer.Builder() - .customization(Consumer { it.setPrivilegedMode(true) }) - .build() - .start() - .use { ubuntu -> - ubuntu.toSsh().newConnection().use { ssh -> - mysql.setup(ssh) - mysql.start(URI("https://dummy-jira.net"), ssh) - } + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { ssh -> + mysql.setup(ssh) + mysql.start(URI("https://dummy-jira.net"), ssh) } + } } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt index 12a7f0ba..1c307690 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt @@ -1,9 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.dataset import com.atlassian.performance.tools.infrastructure.Ls -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.ssh.api.Ssh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions import org.junit.Test import java.net.URI @@ -21,8 +20,8 @@ class HttpDatasetPackageIT { downloadTimeout = Duration.ofMinutes(1) ) - val filesInDataset = SshUbuntuContainer.Builder().build().start().use { sshUbuntu -> - val ssh = sshUbuntu.toSsh() + val filesInDataset = DockerInfrastructure().use { infra -> + val ssh = infra.serve(80, "HttpDatasetPackageIT").ssh return@use RandomFilesGenerator(ssh).start().use { ssh.newConnection().use { connection -> val unpackedPath = dataset.download(connection) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraServiceDeskDistributionIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraServiceDeskDistributionIT.kt index 4ee1a021..4635244c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraServiceDeskDistributionIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraServiceDeskDistributionIT.kt @@ -1,7 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.distribution -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import org.assertj.core.api.Assertions.assertThat import org.junit.Test @@ -9,9 +8,11 @@ class PublicJiraServiceDeskDistributionIT { @Test fun shouldDownloadJiraServiceDesk() { - SshUbuntuContainer.Builder().build().start().use { ssh -> - ssh.toSsh().newConnection().use { connection -> - val distro = PublicJiraServiceDeskDistribution("4.0.1") + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { connection -> + val distro: ProductDistribution = PublicJiraServiceDeskDistribution("4.0.1") + val targetFolder = "test" + connection.execute("mkdir $targetFolder") val installation = distro.install(connection, "destination") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraSoftwareDistributionsIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraSoftwareDistributionsIT.kt index 399259a6..88210083 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraSoftwareDistributionsIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/distribution/PublicJiraSoftwareDistributionsIT.kt @@ -1,10 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.distribution +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraGcLog import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig import com.atlassian.performance.tools.infrastructure.api.jira.SetenvSh -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat import org.junit.Test @@ -12,9 +11,11 @@ class PublicJiraSoftwareDistributionsIT { @Test fun shouldDownloadJiraSoftware() { - SshUbuntuContainer.Builder().build().start().use { ssh -> - ssh.toSsh().newConnection().use { connection -> - val distro = PublicJiraSoftwareDistribution("7.2.0") + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { connection -> + val distro: ProductDistribution = PublicJiraSoftwareDistribution("7.2.0") + val targetFolder = "test" + connection.execute("mkdir $targetFolder") val installation = distro.install(connection, "destination") @@ -26,8 +27,8 @@ class PublicJiraSoftwareDistributionsIT { @Test fun shouldInstallReleaseCandidate() { - SshUbuntuContainer.Builder().build().start().use { ssh -> - ssh.toSsh().newConnection().use { connection -> + DockerInfrastructure().use { infra -> + infra.serveSsh().newConnection().use { connection -> val distro = PublicJiraSoftwareDistribution("9.0.0-RC01") val installation = distro.install(connection, "destination") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index aeb25f99..711dec3b 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -13,7 +13,7 @@ import java.nio.file.Paths class PreInstallHooksTest { private val dummySsh = Ssh(SshHost("localhost", "dummyUser", Paths.get("dummyKey"))) - private val dummyServer = TcpHost("doesn't matter", 123, "fake-server", dummySsh) + private val dummyServer = TcpHost("dummyPublicIp", "dummyPrivateIp", 123, "fake-server", dummySsh) @Test fun shouldInsertDuringListing() { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkSupport.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkSupport.kt index edb98e12..8e653bb0 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkSupport.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkSupport.kt @@ -1,15 +1,14 @@ package com.atlassian.performance.tools.infrastructure.api.jvm -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import org.assertj.core.api.Assertions.assertThat class JdkSupport( private val jdk: VersionedJavaDevelopmentKit ) { fun shouldHaveJavaHomeSet(expectedJavaPath: String) { - SshUbuntuContainer.Builder().build().start().use { ubuntu -> - val ssh = ubuntu.toSsh() + DockerInfrastructure().use { infra -> + val ssh = infra.serveSsh() ssh.newConnection().use { connection -> jdk.install(connection) val javaHomeOutput = connection.execute("source ~/.profile; echo \$JAVA_HOME").output diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt index a4f0f52f..024d47bb 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt @@ -1,11 +1,11 @@ package com.atlassian.performance.tools.infrastructure.api.jvm -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat import java.io.File import java.time.Duration @@ -31,8 +31,8 @@ class JstatSupport( private val jar = "/com/atlassian/performance/tools/infrastructure/api/jvm/$jarName" fun shouldSupportJstat() { - SshUbuntuContainer.Builder().build().start().use { ubuntu -> - val ssh = ubuntu.toSsh() + DockerInfrastructure().use { infra -> + val ssh = infra.serveSsh() ssh.newConnection().use { connection -> shouldSupportJstat(ssh, connection) } @@ -40,6 +40,7 @@ class JstatSupport( } private fun shouldSupportJstat(ssh: Ssh, connection: SshConnection) { + Ubuntu().install(connection, listOf("screen"), Duration.ofMinutes(2)) connection.upload(File(this.javaClass.getResource(jar).toURI()), jarName) jdk.install(connection) ssh.runInBackground(jdk.command("-classpath $jarName samples.HelloWorld")) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt index 84e980a7..61e4e128 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt @@ -1,11 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.jvm -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat import java.time.Duration @@ -13,8 +12,8 @@ class ThreadDumpTest( private val jdk: JavaDevelopmentKit ) { fun shouldGatherThreadDump() { - SshUbuntuContainer.Builder().build().start().use { ubuntu -> - val ssh = ubuntu.toSsh() + DockerInfrastructure().use { infra -> + val ssh = infra.serveSsh() ssh.newConnection().use { connection -> shouldGatherThreadDump(ssh, connection) } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt index 662d872c..3305a5bd 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt @@ -1,10 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.os -import com.atlassian.performance.tools.infrastructure.toSsh +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.ssh.api.SshConnection import com.atlassian.performance.tools.ssh.api.SshHost -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntu -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.apache.logging.log4j.Level import org.junit.After import org.junit.Before @@ -14,23 +14,25 @@ import java.util.concurrent.* class UbuntuIT { private lateinit var executor: ExecutorService - private lateinit var sshUbuntu: SshUbuntu + private lateinit var infra: Infrastructure + private lateinit var sshUbuntu: TcpHost @Before fun before() { executor = Executors.newCachedThreadPool() - sshUbuntu = SshUbuntuContainer.Builder().build().start() + infra = DockerInfrastructure() + sshUbuntu = infra.serve(80, "UbuntuIT") } @After fun after() { - sshUbuntu.close() + infra.close() executor.shutdownNow() } @Test fun shouldRetry() { - sshUbuntu.toSsh().newConnection().use { connection -> + sshUbuntu.ssh.newConnection().use { connection -> Ubuntu().install( ColdAptSshConnection(connection), listOf("nano"), @@ -80,7 +82,7 @@ class UbuntuIT { fun shouldBeThreadSafe() { val completion = ExecutorCompletionService(executor) val readyToUseUbuntu = CountDownLatch(1) - val ssh = sshUbuntu.toSsh() + val ssh = sshUbuntu.ssh val installations = List(5) { Callable { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt index f3042d1f..ea73a2bf 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt @@ -1,19 +1,19 @@ package com.atlassian.performance.tools.infrastructure.api.profiler +import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.infrastructure.api.os.RemotePath -import com.atlassian.performance.tools.infrastructure.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.jira.install.TcpServer -import com.atlassian.performance.tools.infrastructure.jira.start.JiraLaunchScript -import com.atlassian.performance.tools.infrastructure.toSsh -import com.atlassian.performance.tools.sshubuntu.api.SshUbuntuContainer import org.assertj.core.api.Assertions.assertThat import org.junit.Test import java.nio.file.Files.createTempFile -import java.util.function.Consumer class AsyncProfilerIT { @@ -32,17 +32,16 @@ class AsyncProfilerIT { val profiler = AsyncProfiler() testOnInstalledJira(ubuntuVersion) { installedJira -> - val sshClient = installedJira.server.ssh - sshClient.newConnection().use { ssh -> + installedJira.host.ssh.newConnection().use { ssh -> // when profiler.install(ssh) - val startedJira = JiraLaunchScript().start(installedJira) + val startedJira = JiraLaunchScript().start(installedJira, Reports()) val process = profiler.start(ssh, startedJira.pid) Thread.sleep(5000) process.stop(ssh) // then - val profilerResult = RemotePath(sshClient.host, process.getResultPath()) + val profilerResult = RemotePath(installedJira.host.ssh.host, process.getResultPath()) .download(createTempFile("profiler-result", ".svg")) assertThat(profilerResult.readLines().take(5)).contains("") } @@ -50,27 +49,13 @@ class AsyncProfilerIT { } private fun testOnInstalledJira(ubuntuVersion: String, test: (InstalledJira) -> T) { - val privatePort = 8080 - val container = SshUbuntuContainer.Builder() - .version(ubuntuVersion) - .customization(Consumer { - it.addExposedPort(privatePort) - it.setPrivilegedMode(true) - }) - .build() - container.start().use { sshUbuntu -> - val server = TcpServer( - "localhost", - sshUbuntu.container.getMappedPort(privatePort), - privatePort, - "my-jira", - sshUbuntu.toSsh() - ) + DockerInfrastructure(ubuntuVersion).use { infra -> + val jiraNode: JiraNode = infra.serve(listOf(JiraNodePlan.Builder().build())).first() val installed = ParallelInstallation( jiraHomeSource = EmptyJiraHome(), productDistribution = PublicJiraSoftwareDistribution("7.13.0"), jdk = AdoptOpenJDK() - ).install(server) + ).install(jiraNode.host, Reports()) test(installed) } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/ConnectedContainer.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/ConnectedContainer.kt new file mode 100644 index 00000000..ee5ae626 --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/ConnectedContainer.kt @@ -0,0 +1,30 @@ +package com.atlassian.performance.tools.infrastructure.lib.docker + +import com.github.dockerjava.api.DockerClient +import com.github.dockerjava.api.command.ConnectToNetworkCmd + +class ConnectedContainer( + private val docker: DockerClient, + val containerId: String, + val networkId: String +) : AutoCloseable { + + override fun close() { + docker + .disconnectFromNetworkCmd() + .withContainerId(containerId) + .withNetworkId(networkId) + .exec() + } +} + +fun ConnectToNetworkCmd.execAsResource( + docker: DockerClient +): ConnectedContainer { + exec() + return ConnectedContainer( + docker, + containerId!!, + networkId!! + ) +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/CreatedContainer.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/CreatedContainer.kt new file mode 100644 index 00000000..b06863ec --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/CreatedContainer.kt @@ -0,0 +1,18 @@ +package com.atlassian.performance.tools.infrastructure.lib.docker + +import com.github.dockerjava.api.DockerClient +import com.github.dockerjava.api.command.CreateContainerCmd +import com.github.dockerjava.api.command.CreateContainerResponse + +class CreatedContainer( + private val docker: DockerClient, + val response: CreateContainerResponse +) : AutoCloseable { + override fun close() { + docker.removeContainerCmd(response.id).exec() + } +} + +fun CreateContainerCmd.execAsResource( + docker: DockerClient +): CreatedContainer = CreatedContainer(docker, exec()) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/DockerNetwork.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/DockerNetwork.kt new file mode 100644 index 00000000..c137d153 --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/DockerNetwork.kt @@ -0,0 +1,18 @@ +package com.atlassian.performance.tools.infrastructure.lib.docker + +import com.github.dockerjava.api.DockerClient +import com.github.dockerjava.api.command.CreateNetworkCmd +import com.github.dockerjava.api.command.CreateNetworkResponse + +class DockerNetwork( + private val docker: DockerClient, + val response: CreateNetworkResponse +) : AutoCloseable { + override fun close() { + docker.removeNetworkCmd(response.id).exec() + } +} + +fun CreateNetworkCmd.execAsResource( + docker: DockerClient +): DockerNetwork = DockerNetwork(docker, exec()) \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/StartedContainer.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/StartedContainer.kt new file mode 100644 index 00000000..076a02a7 --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/lib/docker/StartedContainer.kt @@ -0,0 +1,23 @@ +package com.atlassian.performance.tools.infrastructure.lib.docker + +import com.github.dockerjava.api.DockerClient +import com.github.dockerjava.api.command.StartContainerCmd + +class StartedContainer( + private val docker: DockerClient, + val id: String +) : AutoCloseable { + override fun close() { + docker.stopContainerCmd(id).exec() + } +} + +fun StartContainerCmd.execAsResource( + docker: DockerClient +): StartedContainer { + exec() + return StartedContainer( + docker, + containerId!! + ) +} From cc4d01e9a741b7195e77f7bef23d58aa523bebb0 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 12 Apr 2021 10:07:20 +0200 Subject: [PATCH 18/73] Try to fix Docker SSH connectivity To read: * https://danwalsh.livejournal.com/74095.html * https://github.com/bmuschko/gradle-docker-plugin/issues/890 Maybe it's because of multiple port exports? --- .../api/DockerInfrastructure.kt | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 74c3eca1..0674a03f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -58,44 +58,51 @@ internal class DockerInfrastructure( .createContainerCmd("rastasheep/ubuntu-sshd:18.04") .withHostConfig( HostConfig() - .withPublishAllPorts(true) -// .withPrivileged(true) - .withBinds(Bind(dockerDaemonSocket, Volume(dockerDaemonSocket))) + .withPublishAllPorts(false) + .withPortBindings( + PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(22)), + PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(port)) + ) + .withPrivileged(false) + .withNetworkMode(network.response.id) +// .withSecurityOpts(emptyList()) +// .withUsernsMode("host") +// .withBinds(Bind(dockerDaemonSocket, Volume(dockerDaemonSocket))) ) - .withExposedPorts(exposedPort) + .withExposedPorts(exposedPort, ExposedPort.tcp(22)) .withName(name + "-" + UUID.randomUUID()) .execAsResource(docker) allocatedResources.addLast(createdContainer) return start(createdContainer, exposedPort) } - private fun start( - created: CreatedContainer, - port: ExposedPort - ): TcpHost { - val connectedContainer = docker - .connectToNetworkCmd() - .withContainerId(created.response.id) - .withNetworkId(network.response.id) - .execAsResource(docker) - allocatedResources.addLast(connectedContainer) - return start(connectedContainer, port) - } +// private fun start( +// created: CreatedContainer, +// port: ExposedPort +// ): TcpHost { +// val connectedContainer = docker // TODO remove? +// .connectToNetworkCmd() +// .withContainerId(created.response.id) +// .withNetworkId(network.response.id) +// .execAsResource(docker) +// allocatedResources.addLast(connectedContainer) +// return start(created, port) +// } private fun start( - connected: ConnectedContainer, + created: CreatedContainer, port: ExposedPort ): TcpHost { val startedContainer = docker - .startContainerCmd(connected.containerId) + .startContainerCmd(created.response.id) .execAsResource(docker) allocatedResources.addLast(startedContainer); - return install(startedContainer, connected, port) + return install(startedContainer, port) } private fun install( started: StartedContainer, - connected: ConnectedContainer, +// connected: ConnectedContainer, port: ExposedPort ): TcpHost { val networkSettings = docker @@ -105,7 +112,7 @@ internal class DockerInfrastructure( val ip = networkSettings .networks .values - .single { it.networkID == connected.networkId } + .single { it.networkID == network.response.id } .ipAddress!! val portBindings = networkSettings.ports.bindings val sshPort = getHostPort(portBindings, ExposedPort.tcp(22)) @@ -125,7 +132,7 @@ internal class DockerInfrastructure( } private fun getHostPort( - portBindings: MutableMap>, + portBindings: Map>, port: ExposedPort ): Int { return portBindings[port]!! From cdbe5cd74163471c77ad8cf0125fa39dfb9924b4 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 23 Apr 2021 13:24:32 +0200 Subject: [PATCH 19/73] Fix Jira-MySQL connectivity across Docker infra --- .../api/jira/install/TcpHost.kt | 2 + .../infrastructure/api/jvm/AdoptOpenJDK.kt | 1 + .../api/DockerInfrastructure.kt | 60 ++++++--------- .../api/jira/instance/JiraDataCenterPlanIT.kt | 73 ++++++++++++++----- 4 files changed, 81 insertions(+), 55 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt index 75862d76..5c06e3f8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt @@ -4,6 +4,8 @@ import com.atlassian.performance.tools.ssh.api.Ssh /** * Has open TCP sockets. + * @param [ssh] connects to the host via [publicIp] + * @param [port] accepts connections at within the [privateIp] network */ class TcpHost( val publicIp: String, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt index f4a26119..823fe87d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt @@ -19,6 +19,7 @@ class AdoptOpenJDK : VersionedJavaDevelopmentKit { override fun getMajorVersion() = 8 override fun install(connection: SshConnection) { + Ubuntu().install(connection, listOf("curl")) download(connection) connection.execute("tar -xzf $jdkArchive") connection.execute("echo '${use()}' >> ~/.profile") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 0674a03f..f4973778 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -15,6 +15,7 @@ import com.github.dockerjava.core.DockerClientImpl import com.github.dockerjava.zerodep.ZerodepDockerHttpClient import java.time.Duration import java.util.* +import java.util.UUID.randomUUID import java.util.concurrent.ConcurrentLinkedDeque internal class DockerInfrastructure( @@ -33,14 +34,15 @@ internal class DockerInfrastructure( allocatedResources.add(docker) network = docker .createNetworkCmd() - .withName(UUID.randomUUID().toString()) + .withName(randomUUID().toString()) .execAsResource(docker) allocatedResources.add(network) } override fun serve(jiraNodePlans: List): List { return jiraNodePlans.mapIndexed { nodeIndex, plan -> - plan.materialize(serve(8080, "jira-node-$nodeIndex")) + val nodeNumber = nodeIndex + 1 + plan.materialize(serve(8080, "jira-node-$nodeNumber")) } } @@ -53,57 +55,41 @@ internal class DockerInfrastructure( .exec(PullImageResultCallback()) .awaitCompletion() val exposedPort = ExposedPort.tcp(port) - val dockerDaemonSocket = "/var/run/docker.sock" val createdContainer = docker .createContainerCmd("rastasheep/ubuntu-sshd:18.04") .withHostConfig( HostConfig() - .withPublishAllPorts(false) - .withPortBindings( - PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(22)), - PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(port)) - ) - .withPrivileged(false) + .withPublishAllPorts(true) +// .withPortBindings( +// PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(22)), +// PortBinding(Ports.Binding("0.0.0.0", "0"), exposedPort) +// ) + .withPrivileged(true) .withNetworkMode(network.response.id) -// .withSecurityOpts(emptyList()) -// .withUsernsMode("host") -// .withBinds(Bind(dockerDaemonSocket, Volume(dockerDaemonSocket))) ) .withExposedPorts(exposedPort, ExposedPort.tcp(22)) - .withName(name + "-" + UUID.randomUUID()) + .withName("$name-${randomUUID()}") .execAsResource(docker) allocatedResources.addLast(createdContainer) - return start(createdContainer, exposedPort) + return start(createdContainer, exposedPort, name) } -// private fun start( -// created: CreatedContainer, -// port: ExposedPort -// ): TcpHost { -// val connectedContainer = docker // TODO remove? -// .connectToNetworkCmd() -// .withContainerId(created.response.id) -// .withNetworkId(network.response.id) -// .execAsResource(docker) -// allocatedResources.addLast(connectedContainer) -// return start(created, port) -// } - private fun start( created: CreatedContainer, - port: ExposedPort + port: ExposedPort, + name: String ): TcpHost { val startedContainer = docker .startContainerCmd(created.response.id) .execAsResource(docker) allocatedResources.addLast(startedContainer); - return install(startedContainer, port) + return install(startedContainer, port, name) } private fun install( started: StartedContainer, -// connected: ConnectedContainer, - port: ExposedPort + port: ExposedPort, + name: String ): TcpHost { val networkSettings = docker .inspectContainerCmd(started.id) @@ -114,9 +100,7 @@ internal class DockerInfrastructure( .values .single { it.networkID == network.response.id } .ipAddress!! - val portBindings = networkSettings.ports.bindings - val sshPort = getHostPort(portBindings, ExposedPort.tcp(22)) - val tcpPort = getHostPort(portBindings, port) + val sshPort = getHostPort(networkSettings, ExposedPort.tcp(22)) val sshHost = SshHost( ipAddress = "localhost", userName = "root", @@ -128,14 +112,16 @@ internal class DockerInfrastructure( it.execute("apt-get update", Duration.ofMinutes(2)) it.execute("apt-get -y install sudo gnupg screen") } - return TcpHost("localhost", ip, tcpPort, started.id, ssh) + return TcpHost("localhost", ip, port.port, name, ssh) } private fun getHostPort( - portBindings: Map>, + networkSettings: NetworkSettings, port: ExposedPort ): Int { - return portBindings[port]!! + return networkSettings + .ports + .bindings[port]!! .single() .hostPortSpec .toInt() diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 903913e7..c306e739 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -52,30 +52,67 @@ class JiraDataCenterPlanIT { .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) + // when + val dataCenter = dcPlan.materialize() + + // then + dataCenter.nodes.forEach { node -> + val installed = node.installed + val serverXml = installed + .installation + .resolve("conf/server.xml") + .download(Files.createTempFile("downloaded-config", ".xml")) + assertThat(serverXml.readText()).contains(" - val installed = node.installed - val serverXml = installed - .installation - .resolve("conf/server.xml") - .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" Date: Fri, 23 Apr 2021 15:57:06 +0200 Subject: [PATCH 20/73] JCES-273: Add load balancers to Data Center --- .../infrastructure/api/Infrastructure.kt | 7 +- .../api/jira/instance/JiraDataCenterPlan.kt | 22 ++--- .../api/loadbalancer/ApacheProxyPlan.kt | 81 +++++++++++++++++++ .../api/loadbalancer/LoadBalancerPlan.kt | 7 ++ .../api/DockerInfrastructure.kt | 22 ++--- .../api/jira/instance/JiraDataCenterPlanIT.kt | 26 ++++-- .../api/profiler/AsyncProfilerIT.kt | 4 +- 7 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt index de596b36..f01ba8b2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -1,10 +1,11 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan interface Infrastructure : AutoCloseable { - fun serve(jiraNodePlans: List): List + + /** + * @return can be reached by the caller via [TcpHost.publicIp] and by the rest of the infra via [TcpHost.privateIp] + */ fun serve(port: Int, name: String): TcpHost } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index ac5be1ca..8efbaa8f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -7,17 +7,17 @@ import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer +import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancerPlan import java.net.URI import java.time.Duration -import java.util.function.Supplier import kotlin.streams.asStream import kotlin.streams.toList class JiraDataCenterPlan constructor( - val nodePlans: List, - val instanceHooks: PreInstanceHooks, - val loadBalancerSupplier: Supplier, - val infrastructure: Infrastructure + private val nodePlans: List, + private val instanceHooks: PreInstanceHooks, + private val balancerPlan: LoadBalancerPlan, + private val infrastructure: Infrastructure ) : JiraInstancePlan { private val reports: Reports = Reports() @@ -25,13 +25,17 @@ class JiraDataCenterPlan constructor( override fun materialize(): JiraInstance { instanceHooks.call(nodePlans.map { it.hooks }, reports) - val nodes = infrastructure.serve(nodePlans) + val nodes = nodePlans.mapIndexed { nodeIndex, nodePlan -> + val nodeNumber = nodeIndex + 1 + val host = infrastructure.serve(8080, "jira-node-$nodeNumber") + nodePlan.materialize(host) + } + val balancer = balancerPlan.materialize(nodes) val installed = installInParallel(nodes) val started = installed.map { it.start(reports) } - val loadBalancer = loadBalancerSupplier.get() - val instance = JiraDataCenter(started, loadBalancer) + val instance = JiraDataCenter(started, balancer) instanceHooks.postInstance.call(instance, reports) - loadBalancer.waitUntilHealthy(loadBalancingPatience) + balancer.waitUntilHealthy(loadBalancingPatience) return instance } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt new file mode 100644 index 00000000..4d4b9578 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -0,0 +1,81 @@ +package com.atlassian.performance.tools.infrastructure.api.loadbalancer + +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.Sed +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff +import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.net.URI +import java.time.Duration + +class ApacheProxyPlan( + private val httpPort: Int, + private val infrastructure: Infrastructure +) : LoadBalancerPlan { + + private val configPath = "/etc/apache2/sites-enabled/000-default.conf" + + override fun materialize(nodes: List): LoadBalancer { + val proxyNode = infrastructure.serve(httpPort, "apache-proxy") + IdempotentAction("Installing and configuring apache load balancer") { + proxyNode.ssh.newConnection().use { connection -> + tryToProvision(connection, nodes) + } + }.retry(2, ExponentialBackoff(Duration.ofSeconds(5))) + val balancerEndpoint = URI("http://${proxyNode.privateIp}:$httpPort/") + nodes.forEach { it.plan.hooks.preStart.insert(InjectProxy(balancerEndpoint)) } + return ApacheProxy(balancerEndpoint) + } + + private fun tryToProvision(ssh: SshConnection, nodes: List) { + Ubuntu().install(ssh, listOf("apache2")) + ssh.execute("sudo rm $configPath") + ssh.execute("sudo touch $configPath") + val mods = listOf( + "proxy", "proxy_ajp", "proxy_http", "rewrite", "deflate", "headers", "proxy_balancer", "proxy_connect", + "proxy_html", "xml2enc", "lbmethod_byrequests" + ) + ssh.execute("sudo a2enmod ${mods.joinToString(" ")}") + appendConfig( + ssh, + "Header add Set-Cookie \\\"ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/\\\" env=BALANCER_ROUTE_CHANGED" + ) + appendConfig(ssh, "") + nodes.forEachIndexed { index, node -> + appendConfig(ssh, "\tBalancerMember http://${node.host.publicIp}:${node.host.port} route=$index") + } + appendConfig(ssh, "\n") + appendConfig(ssh, "ProxyPass / balancer://mycluster/ stickysession=ROUTEID") + appendConfig(ssh, "ProxyPassReverse / balancer://mycluster/ stickysession=ROUTEID") + ssh.execute("sudo service apache2 restart", Duration.ofMinutes(3)) + } + + private fun appendConfig(connection: SshConnection, line: String) { + connection.execute("echo \"$line\" | sudo tee -a $configPath") + } + + private class ApacheProxy( + override val uri: URI + ) : LoadBalancer { + override fun waitUntilHealthy(timeout: Duration) {} + } + + private class InjectProxy( + private val proxy: URI + ) : PreStartHook { + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PreStartHooks, reports: Reports) { + Sed().replace( + ssh, + "bindOnInit=\"false\"", + "bindOnInit=\"false\" scheme=\"http\" proxyName=\"${proxy.host}\" proxyPort=\"${proxy.port}\"", + "${jira.installation.path}/conf/server.xml" + ) + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt new file mode 100644 index 00000000..a433661b --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt @@ -0,0 +1,7 @@ +package com.atlassian.performance.tools.infrastructure.api.loadbalancer + +import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode + +interface LoadBalancerPlan { + fun materialize(nodes: List): LoadBalancer +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index f4973778..38abc406 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -1,15 +1,18 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan -import com.atlassian.performance.tools.infrastructure.lib.docker.* +import com.atlassian.performance.tools.infrastructure.lib.docker.CreatedContainer +import com.atlassian.performance.tools.infrastructure.lib.docker.DockerNetwork +import com.atlassian.performance.tools.infrastructure.lib.docker.StartedContainer +import com.atlassian.performance.tools.infrastructure.lib.docker.execAsResource import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshHost import com.atlassian.performance.tools.ssh.api.auth.PasswordAuthentication import com.github.dockerjava.api.DockerClient import com.github.dockerjava.api.command.PullImageResultCallback -import com.github.dockerjava.api.model.* +import com.github.dockerjava.api.model.ExposedPort +import com.github.dockerjava.api.model.HostConfig +import com.github.dockerjava.api.model.NetworkSettings import com.github.dockerjava.core.DefaultDockerClientConfig import com.github.dockerjava.core.DockerClientImpl import com.github.dockerjava.zerodep.ZerodepDockerHttpClient @@ -39,13 +42,6 @@ internal class DockerInfrastructure( allocatedResources.add(network) } - override fun serve(jiraNodePlans: List): List { - return jiraNodePlans.mapIndexed { nodeIndex, plan -> - val nodeNumber = nodeIndex + 1 - plan.materialize(serve(8080, "jira-node-$nodeNumber")) - } - } - fun serveSsh(): Ssh = serve(888, "ssh").ssh override fun serve(port: Int, name: String): TcpHost { @@ -60,10 +56,6 @@ internal class DockerInfrastructure( .withHostConfig( HostConfig() .withPublishAllPorts(true) -// .withPortBindings( -// PortBinding(Ports.Binding("0.0.0.0", "0"), ExposedPort.tcp(22)), -// PortBinding(Ports.Binding("0.0.0.0", "0"), exposedPort) -// ) .withPrivileged(true) .withNetworkMode(network.response.id) ) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index c306e739..690772e4 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -5,17 +5,23 @@ import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK +import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan +import com.atlassian.performance.tools.ssh.api.SshConnection import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before import org.junit.Test +import java.lang.Exception import java.nio.file.Files -import java.util.function.Supplier class JiraDataCenterPlanIT { @@ -48,9 +54,9 @@ class JiraDataCenterPlanIT { .build() } val instanceHooks = PreInstanceHooks.default() - // TODO this plus `EmptyJiraHome()` = failing `DatabaseIpConfig` - couple them together or stop expecting a preexisting `dbconfig.xml`? but then what about missing lucene indexes? .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } - val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) + val balancerPlan = ApacheProxyPlan(80, infrastructure) + val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) // when val dataCenter = dcPlan.materialize() @@ -71,6 +77,12 @@ class JiraDataCenterPlanIT { @Test fun shouldProvideLogsToDiagnoseFailure() { // given + class FailingHook : PreStartHook { + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PreStartHooks, reports: Reports) { + throw Exception("Failing deliberately before Jira starts") + } + } + val nodePlans = listOf(1, 2).map { JiraNodePlan.Builder() .installation( @@ -81,13 +93,11 @@ class JiraDataCenterPlanIT { ) ) .start(JiraLaunchScript()) - .hooks(PreInstallHooks.default().also { Datasets.JiraSevenDataset.hookMysql(it.postStart) }) + .hooks(PreInstallHooks.default().also { it.preStart.insert(FailingHook()) }) .build() } - val instanceHooks = PreInstanceHooks.default() - // TODO this plus `EmptyJiraHome()` = failing `DatabaseIpConfig` - couple them together or stop expecting a preexisting `dbconfig.xml`? but then what about missing lucene indexes? - .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } - val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, Supplier { TODO() }, infrastructure) + val balancerPlan = ApacheProxyPlan(80, infrastructure) + val dcPlan = JiraDataCenterPlan(nodePlans, PreInstanceHooks.default(), balancerPlan, infrastructure) try { // when diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt index ea73a2bf..ae7cc38d 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt @@ -50,12 +50,12 @@ class AsyncProfilerIT { private fun testOnInstalledJira(ubuntuVersion: String, test: (InstalledJira) -> T) { DockerInfrastructure(ubuntuVersion).use { infra -> - val jiraNode: JiraNode = infra.serve(listOf(JiraNodePlan.Builder().build())).first() + val jiraNode = infra.serve(777, "jira") val installed = ParallelInstallation( jiraHomeSource = EmptyJiraHome(), productDistribution = PublicJiraSoftwareDistribution("7.13.0"), jdk = AdoptOpenJDK() - ).install(jiraNode.host, Reports()) + ).install(jiraNode, Reports()) test(installed) } } From acc5052188e65b495ad0b4a2a869e42155621489 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 23 Apr 2021 18:47:38 +0200 Subject: [PATCH 21/73] WIP: Try mounting shared home It fails due to: ``` 2021-04-23T16:36:59,942Z DEBUG Test worker [] [com.atlassian.performance.tools.ssh.SshjConnection] root$ sudo service nfs-kernel-server restart 2021-04-23T16:37:00,977Z DEBUG Test worker [] [com.atlassian.performance.tools.ssh.WaitingCommand.Companion] * Stopping NFS kernel daemon ...done. * Unexporting directories for NFS kernel daemon... ...done. * Exporting directories for NFS kernel daemon... ...fail! 2021-04-23T16:37:00,979Z WARN Test worker [] [com.atlassian.performance.tools.ssh.WaitingCommand.Companion] exportfs: /home/ubuntu/jira-shared-home does not support NFS export ``` Options: * keep trying NFS in Docker (in WSL) * try other FS sharing (FUSE? SAN?) * use different FS sharing in Docker (volumes?) and different in AWS (so SPI, but what is default? maybe no default or maybe bound to `Infrastructure` SPI itself) --- .../infrastructure/api/Infrastructure.kt | 10 ++- .../api/database/DockerMysqlServer.kt | 2 +- .../api/jira/install/hook/DataCenterHook.kt | 26 -------- .../api/jira/instance/JiraDataCenterPlan.kt | 2 +- .../api/jira/instance/JiraServerPlan.kt | 2 +- .../api/jira/instance/SharedHomeHook.kt | 62 +++++++++++++++++++ .../infrastructure/api/jira/report/Reports.kt | 2 +- .../api/loadbalancer/ApacheProxyPlan.kt | 5 +- .../api/DockerInfrastructure.kt | 28 ++++++++- .../infrastructure/api/browser/ChromeIT.kt | 2 +- .../api/dataset/HttpDatasetPackageIT.kt | 2 +- .../api/jira/instance/JiraDataCenterPlanIT.kt | 13 ++-- .../tools/infrastructure/api/os/UbuntuIT.kt | 9 ++- .../api/profiler/AsyncProfilerIT.kt | 2 +- 14 files changed, 116 insertions(+), 51 deletions(-) delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt index f01ba8b2..7fb7c99a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -1,11 +1,15 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.ssh.api.Ssh + +interface Infrastructure : AutoCloseable { // TODO rename to ServerRoom + + val subnet: String -interface Infrastructure : AutoCloseable { - /** * @return can be reached by the caller via [TcpHost.publicIp] and by the rest of the infra via [TcpHost.privateIp] */ - fun serve(port: Int, name: String): TcpHost + fun serveTcp(name: String): TcpHost + fun serveSsh(name: String): Ssh } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index c746910c..f3084b01 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -24,7 +24,7 @@ class DockerMysqlServer private constructor( hooks: PreInstanceHooks, reports: Reports ) { - val server = infrastructure.serve(3306, "mysql") + val server = infrastructure.serveTcp("mysql") val client = server.ssh.newConnection().use { setup(it, server) } nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.privateIp)) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt deleted file mode 100644 index 5ec19a6d..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DataCenterHook.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook - -import com.atlassian.performance.tools.infrastructure.api.jira.SharedHome -import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.ssh.api.SshConnection - -class DataCenterHook( - private val nodeId: String, - private val sharedHome: SharedHome -) : PostInstallHook { - - override fun call( - ssh: SshConnection, - jira: InstalledJira, - hooks: PostInstallHooks, - reports: Reports - ) { - val localSharedHome = sharedHome.localSharedHome - sharedHome.mount(ssh) - val jiraHome = jira.home.path // TODO what's the difference between localSharedHome and jiraHome? should both be hookable? - ssh.execute("echo ehcache.object.port = 40011 >> $jiraHome/cluster.properties") - ssh.execute("echo jira.node.id = $nodeId >> $jiraHome/cluster.properties") - ssh.execute("echo jira.shared.home = `realpath $localSharedHome` >> $jiraHome/cluster.properties") - } -} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 8efbaa8f..0d1d926c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -27,7 +27,7 @@ class JiraDataCenterPlan constructor( instanceHooks.call(nodePlans.map { it.hooks }, reports) val nodes = nodePlans.mapIndexed { nodeIndex, nodePlan -> val nodeNumber = nodeIndex + 1 - val host = infrastructure.serve(8080, "jira-node-$nodeNumber") + val host = infrastructure.serveTcp("jira-node-$nodeNumber") nodePlan.materialize(host) } val balancer = balancerPlan.materialize(nodes) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 322c0034..c9d7da75 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -17,7 +17,7 @@ class JiraServerPlan private constructor( override fun materialize(): JiraInstance { val nodeHooks = listOf(plan).map { it.hooks } hooks.call(nodeHooks, reports) - val jiraNode = infrastructure.serve(8080, "jira-node") + val jiraNode = infrastructure.serveTcp("jira-node") val installed = plan.installation.install(jiraNode, reports) val started = plan.start.start(installed, reports) val instance = JiraServer(started) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt new file mode 100644 index 00000000..17f79860 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt @@ -0,0 +1,62 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.os.RemotePath +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class SharedHomeHook( + private val jiraHomeSource: JiraHomeSource, + private val infrastructure: Infrastructure +) : PreInstanceHook { + private val localHome = "/home/ubuntu/jira-shared-home" + + override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { + val server = infrastructure.serveSsh("shared-home") + server.newConnection().use { ssh -> + download(ssh) + export(ssh) + } + val sharedHome = RemotePath(server.host, localHome) + nodes.forEach { it.postInstall.insert(SharedHomeMount(sharedHome)) } + } + + private fun download(ssh: SshConnection) { + ssh.execute("sudo mkdir -p $localHome") + val jiraHome = jiraHomeSource.download(ssh) + ssh.execute("sudo mv $jiraHome/{data,plugins,import,export} $localHome") + ssh.safeExecute("sudo mv $jiraHome/logos $localHome") + } + + private fun export(ssh: SshConnection): SshConnection.SshResult { + Ubuntu().install(ssh, listOf("nfs-kernel-server")) + val options = "rw,sync,no_subtree_check,no_root_squash" + ssh.execute("sudo echo '$localHome ${infrastructure.subnet}($options)' | sudo tee -a /etc/exports") + return ssh.execute("sudo service nfs-kernel-server restart") + } + + private class SharedHomeMount( + private val sharedHome: RemotePath + ) : PostInstallHook { + + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { + Ubuntu().install(ssh, listOf("nfs-common")) + val mountSource = "${sharedHome.host.ipAddress}:${sharedHome.path}" + val mountTarget = "mounted-shared-home" + ssh.execute("mkdir -p $mountTarget") + ssh.execute("sudo mount -o soft,intr,rsize=8192,wsize=8192 $mountSource $mountTarget") + ssh.execute("sudo chown ubuntu:ubuntu $mountTarget") + val mountedPath = "`realpath $mountTarget`" + val jiraHome = jira.home.path + ssh.execute("echo ehcache.object.port = 40011 >> $jiraHome/cluster.properties") + ssh.execute("echo jira.node.id = ${jira.host.name} >> $jiraHome/cluster.properties") + ssh.execute("echo jira.shared.home = $mountedPath >> $jiraHome/cluster.properties") + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index 1a579e41..84aa3ae9 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -10,7 +10,7 @@ import java.nio.file.Paths import java.util.* import java.util.concurrent.ConcurrentLinkedQueue -class Reports private constructor( +class Reports private constructor( // TODO turn into SPI to allow AWS CLI transport (S3) private val hostReports: Queue ) { constructor() : this(ConcurrentLinkedQueue()) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt index 4d4b9578..6588dddc 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -15,20 +15,19 @@ import java.net.URI import java.time.Duration class ApacheProxyPlan( - private val httpPort: Int, private val infrastructure: Infrastructure ) : LoadBalancerPlan { private val configPath = "/etc/apache2/sites-enabled/000-default.conf" override fun materialize(nodes: List): LoadBalancer { - val proxyNode = infrastructure.serve(httpPort, "apache-proxy") + val proxyNode = infrastructure.serveTcp("apache-proxy") IdempotentAction("Installing and configuring apache load balancer") { proxyNode.ssh.newConnection().use { connection -> tryToProvision(connection, nodes) } }.retry(2, ExponentialBackoff(Duration.ofSeconds(5))) - val balancerEndpoint = URI("http://${proxyNode.privateIp}:$httpPort/") + val balancerEndpoint = URI("http://${proxyNode.privateIp}:${proxyNode.port}/") nodes.forEach { it.plan.hooks.preStart.insert(InjectProxy(balancerEndpoint)) } return ApacheProxy(balancerEndpoint) } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 38abc406..61496b4f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -28,6 +28,7 @@ internal class DockerInfrastructure( private val allocatedResources: Deque = ConcurrentLinkedDeque() private val docker: DockerClient private val network: DockerNetwork + override val subnet: String init { @@ -40,11 +41,34 @@ internal class DockerInfrastructure( .withName(randomUUID().toString()) .execAsResource(docker) allocatedResources.add(network) + subnet = docker + .inspectNetworkCmd() + .withNetworkId(network.response.id) + .exec() + .ipam + .config + .first() + .subnet + } + + fun serveSsh(): Ssh = serveSsh("ssh") + + override fun serveSsh(name: String): Ssh { + return serveTcp(888, name).ssh } - fun serveSsh(): Ssh = serve(888, "ssh").ssh + override fun serveTcp(name: String): TcpHost { + return when { + name.startsWith("jira-node") -> serveTcp(8080, name) // TODO this is a contract on undocumented behavior + name.startsWith("mysql") -> serveTcp(3306, name) + else -> serveTcp( + 888, + name + ) // TODO pre-provision all the hosts rather than on-demand - unlock batch provisioning (CFN Stack), picking EC2 types, SSD storage, TCP port ranges, subnets, etc. + } + } - override fun serve(port: Int, name: String): TcpHost { + private fun serveTcp(port: Int, name: String): TcpHost { docker .pullImageCmd("rastasheep/ubuntu-sshd") .withTag(ubuntuVersion) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt index 788f38ab..1a656c15 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/ChromeIT.kt @@ -11,7 +11,7 @@ class ChromeIT { @Test fun shouldInstallChromeBrowser() { DockerInfrastructure().use { infra -> - infra.serve(80, "ChromeIT").ssh.newConnection().use { connection -> + infra.serveSsh("ChromeIT").newConnection().use { connection -> val wasInstalledBefore = isChromeInstalled(connection) Chrome().install(connection) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt index 1c307690..0281cb58 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/dataset/HttpDatasetPackageIT.kt @@ -21,7 +21,7 @@ class HttpDatasetPackageIT { ) val filesInDataset = DockerInfrastructure().use { infra -> - val ssh = infra.serve(80, "HttpDatasetPackageIT").ssh + val ssh = infra.serveSsh("HttpDatasetPackageIT") return@use RandomFilesGenerator(ssh).start().use { ssh.newConnection().use { connection -> val unpackedPath = dataset.download(connection) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 690772e4..1be1fc17 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -20,7 +20,6 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before import org.junit.Test -import java.lang.Exception import java.nio.file.Files class JiraDataCenterPlanIT { @@ -40,22 +39,26 @@ class JiraDataCenterPlanIT { @Test fun shouldStartDataCenter() { // given + val jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome) val nodePlans = listOf(1, 2).map { + val nodeHooks = PreInstallHooks.default() + .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } JiraNodePlan.Builder() .installation( ParallelInstallation( - jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome), + jiraHomeSource = jiraHomeSource, productDistribution = PublicJiraSoftwareDistribution("7.13.0"), jdk = AdoptOpenJDK() ) ) .start(JiraLaunchScript()) - .hooks(PreInstallHooks.default().also { Datasets.JiraSevenDataset.hookMysql(it.postStart) }) + .hooks(nodeHooks) .build() } val instanceHooks = PreInstanceHooks.default() .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } - val balancerPlan = ApacheProxyPlan(80, infrastructure) + .also { it.insert(SharedHomeHook(jiraHomeSource, infrastructure)) } + val balancerPlan = ApacheProxyPlan(infrastructure) val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) // when @@ -96,7 +99,7 @@ class JiraDataCenterPlanIT { .hooks(PreInstallHooks.default().also { it.preStart.insert(FailingHook()) }) .build() } - val balancerPlan = ApacheProxyPlan(80, infrastructure) + val balancerPlan = ApacheProxyPlan(infrastructure) val dcPlan = JiraDataCenterPlan(nodePlans, PreInstanceHooks.default(), balancerPlan, infrastructure) try { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt index 3305a5bd..a9f4e521 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.os import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection import com.atlassian.performance.tools.ssh.api.SshHost import org.apache.logging.log4j.Level @@ -15,13 +15,13 @@ import java.util.concurrent.* class UbuntuIT { private lateinit var executor: ExecutorService private lateinit var infra: Infrastructure - private lateinit var sshUbuntu: TcpHost + private lateinit var ssh: Ssh @Before fun before() { executor = Executors.newCachedThreadPool() infra = DockerInfrastructure() - sshUbuntu = infra.serve(80, "UbuntuIT") + ssh = infra.serveSsh("UbuntuIT") } @After @@ -32,7 +32,7 @@ class UbuntuIT { @Test fun shouldRetry() { - sshUbuntu.ssh.newConnection().use { connection -> + ssh.newConnection().use { connection -> Ubuntu().install( ColdAptSshConnection(connection), listOf("nano"), @@ -82,7 +82,6 @@ class UbuntuIT { fun shouldBeThreadSafe() { val completion = ExecutorCompletionService(executor) val readyToUseUbuntu = CountDownLatch(1) - val ssh = sshUbuntu.ssh val installations = List(5) { Callable { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt index ae7cc38d..24d38521 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt @@ -50,7 +50,7 @@ class AsyncProfilerIT { private fun testOnInstalledJira(ubuntuVersion: String, test: (InstalledJira) -> T) { DockerInfrastructure(ubuntuVersion).use { infra -> - val jiraNode = infra.serve(777, "jira") + val jiraNode = infra.serveTcp("jira") val installed = ParallelInstallation( jiraHomeSource = EmptyJiraHome(), productDistribution = PublicJiraSoftwareDistribution("7.13.0"), From 1d1aadde077ef3653f8cec99965a789a12c8bd3b Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 May 2021 15:32:57 +0200 Subject: [PATCH 22/73] JPERF-273: Mount shared home via Samba NFS runs in Linux kernel. Docker shares kernel with the host OS. So the host OS might not support NFS (e.g. WSL, CI). Therefore NFS is not portable. However Samba runs in user space. I could emulate NFS with Docker volumes, but it would still leave `NfsSharedHomeHook` untested. --- .../infrastructure/api/Infrastructure.kt | 1 + ...SharedHomeHook.kt => NfsSharedHomeHook.kt} | 6 +- .../api/jira/instance/SambaSharedHomeHook.kt | 86 +++++++++++++++++++ .../api/DockerInfrastructure.kt | 30 ++++--- .../api/jira/instance/JiraDataCenterPlanIT.kt | 2 +- 5 files changed, 109 insertions(+), 16 deletions(-) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/{SharedHomeHook.kt => NfsSharedHomeHook.kt} (95%) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt index 7fb7c99a..06de898f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -11,5 +11,6 @@ interface Infrastructure : AutoCloseable { // TODO rename to ServerRoom * @return can be reached by the caller via [TcpHost.publicIp] and by the rest of the infra via [TcpHost.privateIp] */ fun serveTcp(name: String): TcpHost + fun serve(name: String, tcpPorts: List, udpPorts: List): TcpHost fun serveSsh(name: String): Ssh } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt similarity index 95% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt index 17f79860..467af37c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SharedHomeHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt @@ -11,7 +11,7 @@ import com.atlassian.performance.tools.infrastructure.api.os.RemotePath import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.ssh.api.SshConnection -internal class SharedHomeHook( +internal class NfsSharedHomeHook( private val jiraHomeSource: JiraHomeSource, private val infrastructure: Infrastructure ) : PreInstanceHook { @@ -24,7 +24,7 @@ internal class SharedHomeHook( export(ssh) } val sharedHome = RemotePath(server.host, localHome) - nodes.forEach { it.postInstall.insert(SharedHomeMount(sharedHome)) } + nodes.forEach { it.postInstall.insert(NfsMount(sharedHome)) } } private fun download(ssh: SshConnection) { @@ -41,7 +41,7 @@ internal class SharedHomeHook( return ssh.execute("sudo service nfs-kernel-server restart") } - private class SharedHomeMount( + private class NfsMount( private val sharedHome: RemotePath ) : PostInstallHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt new file mode 100644 index 00000000..4406fe05 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt @@ -0,0 +1,86 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.util.* + +internal class SambaSharedHomeHook( + private val jiraHomeSource: JiraHomeSource, + private val infrastructure: Infrastructure +) : PreInstanceHook { + + override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { + val server = infrastructure.serve("samba-shared-home", listOf(139, 445), listOf(137, 138)) + val mount = server.ssh.newConnection().use { ssh -> + val sharedHome = download(ssh) + export(ssh, sharedHome, server) + } + nodes.forEach { it.postInstall.insert(mount) } + } + + private fun download(ssh: SshConnection): String { + val sharedHome = "/home/ubuntu/jira-shared-home" + ssh.execute("sudo mkdir -p $sharedHome") + val jiraHome = jiraHomeSource.download(ssh) + ssh.execute("sudo mv $jiraHome/{data,plugins,import,export} $sharedHome") + ssh.safeExecute("sudo mv $jiraHome/logos $sharedHome") + return sharedHome + } + + private fun export(ssh: SshConnection, sharedHome: String, server: TcpHost): SambaMount { + Ubuntu().install(ssh, listOf("samba")) + val shareName = "samba-jira-home" + val share = """ + [$shareName] + comment = shared Jira home + path = $sharedHome + read only = no + browsable = no + """.trimIndent() + ssh.execute("echo '$share' | sudo tee -a /etc/samba/smb.conf") + val user = ssh.execute("whoami").output.trim() + val password = generatePassword() + // could transfer password via file, but it's an ephemeral secret anyway + ssh.execute("echo -e '$password\\n$password\\n' | sudo smbpasswd -s -a $user") + ssh.execute("sudo service smbd restart") + return SambaMount(server.privateIp, shareName, user, password) + } + + private fun generatePassword(): String { + val rng = Random() + val chars = ('a'..'Z') + ('A'..'Z') + ('0'..'9') + return (1..32).map { chars[rng.nextInt(chars.size)] }.joinToString("") + } + + private class SambaMount( + private val ip: String, + private val shareName: String, + private val user: String, + private val password: String + ) : PostInstallHook { + + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { + Ubuntu().install(ssh, listOf("cifs-utils")) + val credentials = "username=$user,password=$password" + val mountSource = "//$ip/$shareName" + val mountTarget = "mounted-shared-home" + ssh.execute("mkdir -p $mountTarget") + val localUser = ssh.execute("whoami").output.trim() + ssh.execute("sudo chown $localUser:$localUser $mountTarget") + ssh.execute("sudo mount -t cifs -o $credentials $mountSource $mountTarget") + val sharedHome = "`realpath $mountTarget`" + val nodeHome = jira.home.path + ssh.execute("echo ehcache.object.port = 40011 >> $nodeHome/cluster.properties") + ssh.execute("echo jira.node.id = ${jira.host.name} >> $nodeHome/cluster.properties") + ssh.execute("echo jira.shared.home = $sharedHome >> $nodeHome/cluster.properties") + } + } +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 61496b4f..81391939 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -58,23 +58,29 @@ internal class DockerInfrastructure( } override fun serveTcp(name: String): TcpHost { + // TODO pre-provision all the hosts rather than on-demand - unlock batch provisioning (CFN Stack), picking EC2 types, SSD storage, TCP port ranges, subnets, etc. return when { name.startsWith("jira-node") -> serveTcp(8080, name) // TODO this is a contract on undocumented behavior name.startsWith("mysql") -> serveTcp(3306, name) - else -> serveTcp( - 888, - name - ) // TODO pre-provision all the hosts rather than on-demand - unlock batch provisioning (CFN Stack), picking EC2 types, SSD storage, TCP port ranges, subnets, etc. + name.startsWith("samba") -> serveTcp(3306, name) + else -> serveTcp(888, name) } } - private fun serveTcp(port: Int, name: String): TcpHost { + private fun serveTcp(tcpPort: Int, name: String): TcpHost { + return serve(name, listOf(tcpPort), emptyList()) + } + + + override fun serve(name: String, tcpPorts: List, udpPorts: List): TcpHost { + val ports = tcpPorts.map { ExposedPort.tcp(it) } + + udpPorts.map { ExposedPort.udp(it) } + + ExposedPort.tcp(22) docker .pullImageCmd("rastasheep/ubuntu-sshd") .withTag(ubuntuVersion) .exec(PullImageResultCallback()) .awaitCompletion() - val exposedPort = ExposedPort.tcp(port) val createdContainer = docker .createContainerCmd("rastasheep/ubuntu-sshd:18.04") .withHostConfig( @@ -83,28 +89,28 @@ internal class DockerInfrastructure( .withPrivileged(true) .withNetworkMode(network.response.id) ) - .withExposedPorts(exposedPort, ExposedPort.tcp(22)) + .withExposedPorts(ports) .withName("$name-${randomUUID()}") .execAsResource(docker) allocatedResources.addLast(createdContainer) - return start(createdContainer, exposedPort, name) + return start(createdContainer, tcpPorts.first(), name) } private fun start( created: CreatedContainer, - port: ExposedPort, + tcpPort: Int, name: String ): TcpHost { val startedContainer = docker .startContainerCmd(created.response.id) .execAsResource(docker) allocatedResources.addLast(startedContainer); - return install(startedContainer, port, name) + return install(startedContainer, tcpPort, name) } private fun install( started: StartedContainer, - port: ExposedPort, + tcpPort: Int, name: String ): TcpHost { val networkSettings = docker @@ -128,7 +134,7 @@ internal class DockerInfrastructure( it.execute("apt-get update", Duration.ofMinutes(2)) it.execute("apt-get -y install sudo gnupg screen") } - return TcpHost("localhost", ip, port.port, name, ssh) + return TcpHost("localhost", ip, tcpPort, name, ssh) } private fun getHostPort( diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 1be1fc17..b69dcc7d 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -57,7 +57,7 @@ class JiraDataCenterPlanIT { } val instanceHooks = PreInstanceHooks.default() .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } - .also { it.insert(SharedHomeHook(jiraHomeSource, infrastructure)) } + .also { it.insert(SambaSharedHomeHook(jiraHomeSource, infrastructure)) } val balancerPlan = ApacheProxyPlan(infrastructure) val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) From 00b98cbc446986e3fc56815efb3563fbe2b49170 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 May 2021 16:19:21 +0200 Subject: [PATCH 23/73] JPERF-273: Fix `ApacheProxyPlan` --- .../infrastructure/api/loadbalancer/ApacheProxyPlan.kt | 8 +++++--- .../api/jira/instance/JiraDataCenterPlanIT.kt | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt index 6588dddc..d0edc217 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -3,6 +3,7 @@ package com.atlassian.performance.tools.infrastructure.api.loadbalancer import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.Sed import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook @@ -24,7 +25,7 @@ class ApacheProxyPlan( val proxyNode = infrastructure.serveTcp("apache-proxy") IdempotentAction("Installing and configuring apache load balancer") { proxyNode.ssh.newConnection().use { connection -> - tryToProvision(connection, nodes) + tryToProvision(connection, nodes, proxyNode) } }.retry(2, ExponentialBackoff(Duration.ofSeconds(5))) val balancerEndpoint = URI("http://${proxyNode.privateIp}:${proxyNode.port}/") @@ -32,8 +33,9 @@ class ApacheProxyPlan( return ApacheProxy(balancerEndpoint) } - private fun tryToProvision(ssh: SshConnection, nodes: List) { + private fun tryToProvision(ssh: SshConnection, nodes: List, proxyNode: TcpHost) { Ubuntu().install(ssh, listOf("apache2")) + Sed().replace(ssh, "Listen 80", "Listen ${proxyNode.port}", "/etc/apache2/ports.conf") ssh.execute("sudo rm $configPath") ssh.execute("sudo touch $configPath") val mods = listOf( @@ -47,7 +49,7 @@ class ApacheProxyPlan( ) appendConfig(ssh, "") nodes.forEachIndexed { index, node -> - appendConfig(ssh, "\tBalancerMember http://${node.host.publicIp}:${node.host.port} route=$index") + appendConfig(ssh, "\tBalancerMember http://${node.host.privateIp}:${node.host.port} route=$index") } appendConfig(ssh, "\n") appendConfig(ssh, "ProxyPass / balancer://mycluster/ stickysession=ROUTEID") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index b69dcc7d..1c3e031d 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -73,6 +73,9 @@ class JiraDataCenterPlanIT { .download(Files.createTempFile("downloaded-config", ".xml")) assertThat(serverXml.readText()).contains(" + ssh.execute("wget ${dataCenter.address}") + } } } From fc80a107b48bd2d45ae6fed5623e844178404747 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 May 2021 16:53:00 +0200 Subject: [PATCH 24/73] Resolve conflicts after rebase --- CHANGELOG.md | 14 ++++++++------ .../api/jira/install/InstalledJira.kt | 2 +- .../api/jira/install/JiraInstallation.kt | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77dec6ae..1e392227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -188,12 +188,7 @@ Empty release to test changes in release process. ### Deprecated - `Database.setup(ssh: SshConnection): String` in favor of `Database.performSetup(ssh: SshConnection): DatabaseSetup` -## [4.18.0] - 2021-04-14 -[4.18.0]: https://github.com/atlassian/infrastructure/compare/release-4.17.5...release-4.18.0 - ### Added -- Point to remote files on SSH hosts via `RemotePath`. - Fix [JPERF-273]: - Allow multiple ways of installing Jira via `JiraInstallation` or starting it via `JiraStart`. - Represent the information required to use an already installed Jira via `InstalledJira` or `JiraStart` if started. @@ -203,11 +198,18 @@ Fix [JPERF-273]: - Let hooks insert new hooks. - Locate and download any logs, charts, profiles and other reports via `Report` (rather than hardcoding the paths). +[JPERF-273]: https://ecosystem.atlassian.net/browse/JPERF-273 + +## [4.18.0] - 2021-04-14 +[4.18.0]: https://github.com/atlassian/infrastructure/compare/release-4.17.5...release-4.18.0 + +### Added +- Point to remote files on SSH hosts via `RemotePath`. + ### Fixed - Increase network-level retries for Jira/browser downloads. Decrease flakiness of such downloads on Ubuntu on WSL2. - Download ChromeDriver version that matches installed Chrome version. Fix [JPERF-732]. -[JPERF-273]: https://ecosystem.atlassian.net/browse/JPERF-273 [JPERF-732]: https://ecosystem.atlassian.net/browse/JPERF-732 ## [4.17.5] - 2020-12-15 diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt index 1845ac86..95c77249 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt @@ -6,7 +6,7 @@ import com.atlassian.performance.tools.infrastructure.api.os.RemotePath /** * Points to an already installed Jira. * - * @since 4.18.0 + * @since 4.19.0 */ class InstalledJira( /** diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index 71c0f488..deb4bfb0 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -4,7 +4,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import net.jcip.annotations.ThreadSafe /** - * @since 4.18.0 + * @since 4.19.0 */ @ThreadSafe interface JiraInstallation { From bb2478637b229a799eb2e7357177cbeb1bb017fd Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 11:33:21 +0200 Subject: [PATCH 25/73] Handle multiple Docker port bindings (IP4, IP6) --- .../tools/infrastructure/api/DockerInfrastructure.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 81391939..7e523ce5 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -144,7 +144,7 @@ internal class DockerInfrastructure( return networkSettings .ports .bindings[port]!! - .single() + .single { it.hostIp == "0.0.0.0" } // include just the IP4 bind .hostPortSpec .toInt() } From 6b9a1034915cdd7ecdf04199c23834d257e8fe31 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 13:00:47 +0200 Subject: [PATCH 26/73] Try various DIND on CI --- .../infrastructure/api/DockerInfrastructure.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 7e523ce5..6774e424 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -10,9 +10,7 @@ import com.atlassian.performance.tools.ssh.api.SshHost import com.atlassian.performance.tools.ssh.api.auth.PasswordAuthentication import com.github.dockerjava.api.DockerClient import com.github.dockerjava.api.command.PullImageResultCallback -import com.github.dockerjava.api.model.ExposedPort -import com.github.dockerjava.api.model.HostConfig -import com.github.dockerjava.api.model.NetworkSettings +import com.github.dockerjava.api.model.* import com.github.dockerjava.core.DefaultDockerClientConfig import com.github.dockerjava.core.DockerClientImpl import com.github.dockerjava.zerodep.ZerodepDockerHttpClient @@ -86,9 +84,18 @@ internal class DockerInfrastructure( .withHostConfig( HostConfig() .withPublishAllPorts(true) - .withPrivileged(true) +// .withPrivileged(true) + .withBinds(Bind("/var/run/docker.sock", Volume("/var/run/docker.sock"))) +// .withMounts( +// Mount() +// .withSource("/var/run/docker.sock") +// .withTarget("/var/run/docker.sock") +// .withType(MountType.VOLUME) +// .let { listOf(it) } +// ) .withNetworkMode(network.response.id) ) +// .withVolumes(Volume("/var/run/docker.sock")) .withExposedPorts(ports) .withName("$name-${randomUUID()}") .execAsResource(docker) From 1ea9e83b5c65f7b6561cadd5b7514f6b3cbb8a8f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 13:53:08 +0200 Subject: [PATCH 27/73] Restore privileged Docker for MySQL --- .../tools/infrastructure/api/DockerInfrastructure.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 6774e424..33ec73c3 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -84,7 +84,7 @@ internal class DockerInfrastructure( .withHostConfig( HostConfig() .withPublishAllPorts(true) -// .withPrivileged(true) + .withPrivileged(true) .withBinds(Bind("/var/run/docker.sock", Volume("/var/run/docker.sock"))) // .withMounts( // Mount() From 095d665c7d42ad83c9674dd06b03fbfa22618ae7 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 17:14:39 +0200 Subject: [PATCH 28/73] Replace deprecated `startProcess` in tests --- .../tools/infrastructure/SshExtensions.kt | 9 +++++ .../chromium/PageLoadTimeoutRecoveryTest.kt | 4 +-- .../infrastructure/api/jvm/JstatSupport.kt | 33 ++++++++----------- .../infrastructure/api/jvm/ThreadDumpIT.kt | 6 +++- .../infrastructure/browser/SshChromium.kt | 24 ++++++-------- 5 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshExtensions.kt diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshExtensions.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshExtensions.kt new file mode 100644 index 00000000..201da516 --- /dev/null +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/SshExtensions.kt @@ -0,0 +1,9 @@ +package com.atlassian.performance.tools.infrastructure + +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal fun SshConnection.SshResult.assertInterruptedJava() { + if (exitStatus !in listOf(0, 130)) { + throw Exception("$this doesn't look like an interrupted Java process") + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt index 9699cfcb..e8f952c2 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/browser/chromium/PageLoadTimeoutRecoveryTest.kt @@ -28,7 +28,7 @@ internal class PageLoadTimeoutRecoveryTest { chromium.install(connection) } val chromedriverUri = URI("http://localhost:$localChromedriverPort") - SshChromium(ssh.newConnection(), chromedriverUri).start().use { sshDriver -> + SshChromium(ssh, chromedriverUri).start().use { sshDriver -> val driver = sshDriver.getDriver() setPageLoadTimeout(driver) @@ -46,7 +46,7 @@ internal class PageLoadTimeoutRecoveryTest { } private fun findFreePort(): Int { - return ServerSocket(0).use { socket -> return socket.localPort } + return ServerSocket(0).use { socket -> socket.localPort } } private class FastResponse : MockHttpServer.RequestHandler { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt index 024d47bb..8498718a 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JstatSupport.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jvm import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.assertInterruptedJava import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.ssh.api.Ssh @@ -9,26 +10,14 @@ import com.atlassian.performance.tools.ssh.api.SshConnection import org.assertj.core.api.Assertions.assertThat import java.io.File import java.time.Duration +import java.time.Duration.ofSeconds class JstatSupport( private val jdk: VersionedJavaDevelopmentKit ) { - private val expectedStats: Set = setOf( - "Timestamp", - "S0", - "S1", - "E", - "O", - "M", - "CCS", - "YGC", - "YGCT", - "FGC", - "FGCT", - "GCT" - ) private val jarName = "hello-world-after-1m-wait.jar" - private val jar = "/com/atlassian/performance/tools/infrastructure/api/jvm/$jarName" + private val jarResource = "/com/atlassian/performance/tools/infrastructure/api/jvm/$jarName" + private val timestampLength = "2018-12-17T14:10:44+00:00 ".length fun shouldSupportJstat() { DockerInfrastructure().use { infra -> @@ -41,24 +30,28 @@ class JstatSupport( private fun shouldSupportJstat(ssh: Ssh, connection: SshConnection) { Ubuntu().install(connection, listOf("screen"), Duration.ofMinutes(2)) - connection.upload(File(this.javaClass.getResource(jar).toURI()), jarName) + connection.upload(File(javaClass.getResource(jarResource)!!.toURI()), jarName) jdk.install(connection) - ssh.runInBackground(jdk.command("-classpath $jarName samples.HelloWorld")) + val hello = ssh.runInBackground(jdk.command("-classpath $jarName samples.HelloWorld")) val pid = IdempotentAction("Wait for the Hello, World! process to start.") { connection.execute("cat hello-world.pid").output }.retry( maxAttempts = 3, - backoff = ExponentialBackoff(Duration.ofSeconds(1)) + backoff = ExponentialBackoff(ofSeconds(1)) ) val jstatMonitoring = jdk.jstatMonitoring.start(connection, pid.toInt()) waitForJstatToCollectSomeData() jstatMonitoring.stop(connection) + hello.stop(ofSeconds(1)).assertInterruptedJava(); val jstatLog = connection.execute("head -n 1 ${jstatMonitoring.getResultPath()}").output + val jstatHeader = jstatLog.substring(timestampLength, jstatLog.indexOf('\n')) - assertThat(jstatLog).contains(this.expectedStats) + assertThat(jstatHeader).contains( + "Timestamp", "S0", "S1", "E", "O", "M", "CCS", "YGC", "YGCT", "FGC", "FGCT", "GCT" + ) } private fun waitForJstatToCollectSomeData() { - Thread.sleep(8 * 1000) + Thread.sleep(ofSeconds(8).toMillis()) } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt index 61e4e128..09bbb8a2 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/ThreadDumpIT.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jvm import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure +import com.atlassian.performance.tools.infrastructure.assertInterruptedJava import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.Ssh @@ -25,7 +26,8 @@ class ThreadDumpTest( val destination = "thread-dumps" connection.execute("""echo "public class Test { public static void main(String[] args) { try { Thread.sleep(java.time.Duration.ofMinutes(1).toMillis()); } catch (InterruptedException e) { throw new RuntimeException(e); } }}" > Test.java """.trimIndent()) connection.execute("${jdk.use()}; javac Test.java") - ssh.runInBackground("${jdk.use()}; java Test").use { + val process = ssh.runInBackground("${jdk.use()}; java Test") + try { val pid = IdempotentAction("Get PID") { getPid(connection, jdk) }.retry(maxAttempts = 2, backoff = StaticBackoff(Duration.ofSeconds(1))) @@ -35,6 +37,8 @@ class ThreadDumpTest( val threadDumpFile = connection.execute("ls $destination").output val threadDump = connection.execute("cat $destination/$threadDumpFile").output assertThat(threadDump).contains("Full thread dump Java HotSpot") + } finally { + process.stop(Duration.ofSeconds(1)).assertInterruptedJava() } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/browser/SshChromium.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/browser/SshChromium.kt index 81428ebf..89034461 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/browser/SshChromium.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/browser/SshChromium.kt @@ -2,22 +2,21 @@ package com.atlassian.performance.tools.infrastructure.browser import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff -import com.atlassian.performance.tools.ssh.api.DetachedProcess +import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection import com.atlassian.performance.tools.virtualusers.api.browsers.Browser import com.atlassian.performance.tools.virtualusers.api.browsers.CloseableRemoteWebDriver import org.openqa.selenium.chrome.ChromeOptions import org.openqa.selenium.remote.RemoteWebDriver import java.net.URI -import java.time.Duration +import java.time.Duration.ofSeconds internal class SshChromium( - private val ssh: SshConnection, + private val ssh: Ssh, private val chromedriverUri: URI ) : Browser { override fun start(): CloseableRemoteWebDriver { - val chromedriverProcess: DetachedProcess = ssh.startProcess("chromedriver --whitelisted-ips") - + ssh.runInBackground("chromedriver --whitelisted-ips") val chromeOptions = ChromeOptions() .apply { addArguments("--headless") } .apply { addArguments("--no-sandbox") } @@ -28,16 +27,13 @@ internal class SshChromium( "credentials_enable_service" to false ) ) - IdempotentAction("Wait for chrome process") { - waitForChromeProcess(ssh) - }.retry(maxAttempts = 3, backoff = StaticBackoff(Duration.ofSeconds(5L))) - val driver = RemoteWebDriver(chromedriverUri.toURL(), chromeOptions) - return object : CloseableRemoteWebDriver(driver) { - override fun close() { - super.close() - ssh.stopProcess(chromedriverProcess) - } + ssh.newConnection().use { connection -> + IdempotentAction("Wait for chrome process") { + waitForChromeProcess(connection) + }.retry(3, StaticBackoff(ofSeconds(5))) } + val driver = RemoteWebDriver(chromedriverUri.toURL(), chromeOptions) + return CloseableRemoteWebDriver(driver) } private fun waitForChromeProcess(ssh: SshConnection) { From 1065fdbdd17442c69a5f8ada17b5a6a04257c86f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 17:15:14 +0200 Subject: [PATCH 29/73] Fail fast when docker-in-docker dies --- .../api/database/DockerMysqlServer.kt | 4 ++-- .../tools/infrastructure/database/MySql.kt | 14 ++++++++++++- .../docker/DeadContainerCheck.kt | 20 +++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/docker/DeadContainerCheck.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index f3084b01..247aef8c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -35,7 +35,7 @@ class DockerMysqlServer private constructor( private fun setup(ssh: SshConnection, server: TcpHost): SshSqlClient { val mysqlDataLocation = source.download(ssh) - Mysql.container( + val containerName = Mysql.container( dataDir = mysqlDataLocation, extraParameters = emptyArray(), extraArguments = arrayOf( @@ -46,7 +46,7 @@ class DockerMysqlServer private constructor( ).run(ssh) Ubuntu().install(ssh, listOf("mysql-client")) val client = SshMysqlClient("127.0.0.1", server.port) - Mysql.awaitDatabase(ssh, client) + Mysql.awaitDatabase(ssh, client, containerName) return client } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index 23cbd9c0..49fd00bd 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -3,6 +3,8 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.docker.DeadContainerCheck +import com.atlassian.performance.tools.jvmtasks.api.Backoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection @@ -54,7 +56,17 @@ internal object Mysql { .build() fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient) { + val backoff = StaticBackoff(ofSeconds(10)) + awaitDatabase(ssh, sqlClient, backoff) + } + + fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient, containerName: String) { + val backoff = DeadContainerCheck(containerName, ssh, StaticBackoff(ofSeconds(10))) + awaitDatabase(ssh, sqlClient, backoff) + } + + private fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient, backoff: Backoff) { IdempotentAction("wait for MySQL start") { sqlClient.runSql(ssh, "select 1;") } - .retry(90, StaticBackoff(ofSeconds(10))) + .retry(90, backoff) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/docker/DeadContainerCheck.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/docker/DeadContainerCheck.kt new file mode 100644 index 00000000..9d222c46 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/docker/DeadContainerCheck.kt @@ -0,0 +1,20 @@ +package com.atlassian.performance.tools.infrastructure.docker + +import com.atlassian.performance.tools.jvmtasks.api.Backoff +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.time.Duration + +internal class DeadContainerCheck( + private val container: String, + private val ssh: SshConnection, + private val base: Backoff +) : Backoff { + override fun backOff(attempt: Int): Duration { + val status = ssh.execute("sudo docker inspect --format '{{.State.Status}}' $container").output.trim() + if (status == "exited") { + val logs = ssh.execute("sudo docker logs $container").errorOutput.trim() + throw Exception("$container exited, logs: $logs") + } + return base.backOff(attempt) + } +} \ No newline at end of file From 3ea63faba02edcdda7248135a467ce56bd1488ae Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 14 May 2021 17:17:47 +0200 Subject: [PATCH 30/73] Check Docker info on CI --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e17b21c6..93d7a25e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,8 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Check Docker + run: docker info - name: Checkout uses: actions/checkout@v2 with: From 9c9be29a5fc6a30856de106c75aabbbce01a3e37 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 12:36:26 +0200 Subject: [PATCH 31/73] Undo sibling socket-based "DIND" --- .../tools/infrastructure/api/DockerInfrastructure.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 33ec73c3..a80e1b6c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -85,7 +85,7 @@ internal class DockerInfrastructure( HostConfig() .withPublishAllPorts(true) .withPrivileged(true) - .withBinds(Bind("/var/run/docker.sock", Volume("/var/run/docker.sock"))) +// .withBinds(Bind("/var/run/docker.sock", Volume("/var/run/docker.sock"))) // .withMounts( // Mount() // .withSource("/var/run/docker.sock") From 58c84550dc710009fd2bbfa2e2a8cac28ebbb90a Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 12:37:24 +0200 Subject: [PATCH 32/73] Force Ubuntu Docker to use OverlayFS --- .../tools/infrastructure/api/docker/Docker.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt index dc79ca6d..533e9bb4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt @@ -44,9 +44,18 @@ class Docker private constructor( timeout = mainPackageTimeout ) ssh.execute("sudo service docker status || sudo service docker start") + ssh.safeExecute("sudo cat /etc/docker/daemon.json") IdempotentAction("poll docker") { ssh.execute("sudo docker ps") }.retry(2, StaticBackoff(Duration.ofSeconds(1))) + ssh.execute("sudo docker info") + ssh.execute("echo '{\"storage-driver\": \"overlay2\"}' | sudo tee /etc/docker/daemon.json") + ssh.execute("sudo cat /etc/docker/daemon.json") + ssh.execute("sudo service docker restart") + IdempotentAction("poll docker") { + ssh.execute("sudo docker ps") + }.retry(2, StaticBackoff(Duration.ofSeconds(1))) + ssh.execute("sudo docker info") } class Builder { From a6b37979f2f4861dd41fb2349d7d108c6e584867 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 14:13:53 +0200 Subject: [PATCH 33/73] Try Docker `vfs` on GHA --- .../performance/tools/infrastructure/api/docker/Docker.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt index 533e9bb4..2d01c0fb 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt @@ -49,7 +49,7 @@ class Docker private constructor( ssh.execute("sudo docker ps") }.retry(2, StaticBackoff(Duration.ofSeconds(1))) ssh.execute("sudo docker info") - ssh.execute("echo '{\"storage-driver\": \"overlay2\"}' | sudo tee /etc/docker/daemon.json") + ssh.execute("echo '{\"storage-driver\": \"vfs\"}' | sudo tee /etc/docker/daemon.json") ssh.execute("sudo cat /etc/docker/daemon.json") ssh.execute("sudo service docker restart") IdempotentAction("poll docker") { From 66a3854b5bbd5da38d934904de934d8aacfa4384 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 14:30:06 +0200 Subject: [PATCH 34/73] Use vfs --- .../tools/infrastructure/api/docker/Docker.kt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt index 2d01c0fb..70c65ae9 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/docker/Docker.kt @@ -43,19 +43,12 @@ class Docker private constructor( packages = listOf("docker-ce=$version"), timeout = mainPackageTimeout ) - ssh.execute("sudo service docker status || sudo service docker start") - ssh.safeExecute("sudo cat /etc/docker/daemon.json") - IdempotentAction("poll docker") { - ssh.execute("sudo docker ps") - }.retry(2, StaticBackoff(Duration.ofSeconds(1))) - ssh.execute("sudo docker info") + ssh.execute("sudo mkdir -p /etc/docker") ssh.execute("echo '{\"storage-driver\": \"vfs\"}' | sudo tee /etc/docker/daemon.json") - ssh.execute("sudo cat /etc/docker/daemon.json") - ssh.execute("sudo service docker restart") + ssh.execute("sudo service docker status || sudo service docker start") IdempotentAction("poll docker") { ssh.execute("sudo docker ps") }.retry(2, StaticBackoff(Duration.ofSeconds(1))) - ssh.execute("sudo docker info") } class Builder { From dc795b60972f4e8b78a85c7eaaad08bf6e258641 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 14:51:31 +0200 Subject: [PATCH 35/73] Fix `RestUpgrade` --- .../tools/infrastructure/api/jira/start/hook/RestUpgrade.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index 6cff1183..89c12a00 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -18,8 +18,9 @@ class RestUpgrade( override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val threadDump = ThreadDump(jira.pid, jira.installed.jdk) + val ip = jira.installed.host.privateIp val port = jira.installed.host.port - val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@localhost:$port/rest/api/2/upgrade") + val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@$ip:$port/rest/api/2/upgrade") reports.add(FileListing("thread-dumps/*"), jira.installed.host) waitForStatusToChange( statusQuo = "000", From 53aec65ea52078972204fbe79c694777b4f377e7 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 21 May 2021 17:07:03 +0200 Subject: [PATCH 36/73] Fix the `report` assertions --- .../tools/infrastructure/Datasets.kt | 2 +- .../api/jira/instance/JiraDataCenterPlanIT.kt | 63 ++++++++++--------- .../api/jira/instance/JiraServerPlanIT.kt | 25 +++++--- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 5c475ff2..5c3fb0cb 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -34,7 +34,7 @@ class Datasets { fun hookMysql(postStartHooks: PostStartHooks) { val timeouts = JiraLaunchTimeouts.Builder() - .initTimeout(Duration.ofSeconds(30)) + .initTimeout(Duration.ofSeconds(45)) .build() val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") postStartHooks.insert(dataUpgrade) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 1c3e031d..3d9dcca7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -5,22 +5,24 @@ import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage -import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan import com.atlassian.performance.tools.ssh.api.SshConnection import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable import org.junit.After import org.junit.Before import org.junit.Test import java.nio.file.Files +import java.time.Duration.ofMinutes class JiraDataCenterPlanIT { @@ -83,9 +85,11 @@ class JiraDataCenterPlanIT { @Test fun shouldProvideLogsToDiagnoseFailure() { // given - class FailingHook : PreStartHook { - override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PreStartHooks, reports: Reports) { - throw Exception("Failing deliberately before Jira starts") + class FailingHook : PostStartHook { + override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { + val installed = jira.installed + ssh.execute("${installed.jdk.use()}; ${installed.installation.path}/bin/stop-jira.sh", ofMinutes(1)) + throw Exception("Failing deliberately after Jira started") } } @@ -99,36 +103,35 @@ class JiraDataCenterPlanIT { ) ) .start(JiraLaunchScript()) - .hooks(PreInstallHooks.default().also { it.preStart.insert(FailingHook()) }) + .hooks(PreInstallHooks.default().also { it.postStart.insert(FailingHook()) }) .build() } val balancerPlan = ApacheProxyPlan(infrastructure) val dcPlan = JiraDataCenterPlan(nodePlans, PreInstanceHooks.default(), balancerPlan, infrastructure) - try { - // when + // when + val thrown = catchThrowable { dcPlan.materialize() - } finally { - val reports = dcPlan.report().downloadTo(Files.createTempDirectory("jira-dc-plan-")) - // then - assertThat(reports).isDirectory() - val fileTree = reports - .walkTopDown() - .map { reports.toPath().relativize(it.toPath()) } - .toList() - assertThat(fileTree.map { it.toString() }).contains( - "jira-node-1/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", - "jira-node-1/root/thread-dumps", - "jira-node-2/root/~/jpt-jstat.log", - "jira-node-2/root/~/jpt-vmstat.log", - "jira-node-2/root/~/jpt-iostat.log" - ) - assertThat(fileTree.filter { it.fileName.toString().startsWith("access_log") }) - .`as`("access logs") - .isNotEmpty - assertThat(fileTree.filter { it.fileName.toString().startsWith("atlassian-jira-gc") }) - .`as`("GC logs") - .isNotEmpty } + + val reports = dcPlan.report().downloadTo(Files.createTempDirectory("jira-dc-plan-")) + // then + assertThat(thrown).hasMessageStartingWith("Failing deliberately") + assertThat(reports).isDirectory() + val fileTree = reports + .walkTopDown() + .map { reports.toPath().relativize(it.toPath()) } + .toList() + assertThat(fileTree.map { it.toString() }).contains( + "jira-node-1/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", + "jira-node-1/root/~/jpt-jstat.log", + "jira-node-2/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out" + ) + assertThat(fileTree.filter { it.fileName.toString() == "atlassian-jira.log" }) + .`as`("Jira log from $fileTree") + .isNotEmpty + assertThat(fileTree.filter { it.fileName.toString().startsWith("atlassian-jira-gc") }) + .`as`("GC logs from $fileTree") + .isNotEmpty } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index fdb80901..dc335b9b 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -59,7 +59,7 @@ class JiraServerPlanIT { val theNode = jiraServer.nodes.single() val host = theNode.installed.host - val downloadedReports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) + val reports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) // then val serverXml = theNode @@ -69,12 +69,23 @@ class JiraServerPlanIT { .download(Files.createTempFile("downloaded-config", ".xml")) assertThat(serverXml.readText()).contains(" Date: Fri, 11 Jun 2021 13:47:04 +0200 Subject: [PATCH 37/73] Diagnose `RestUpgrade` failures --- .github/workflows/ci.yml | 6 + .../api/jira/install/hook/JiraLogs.kt | 32 ++--- .../api/jira/start/hook/RestUpgrade.kt | 113 ++++++++++-------- .../api/jira/instance/JiraServerPlanIT.kt | 14 ++- 4 files changed, 99 insertions(+), 66 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93d7a25e..e79bf576 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,12 @@ jobs: with: name: test-reports path: build/reports/tests + - name: Upload test artifacts + if: always() + uses: actions/upload-artifact@v2 + with: + name: test-artifacts + path: build/test-artifacts release: runs-on: ubuntu-latest permissions: diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt index 683f5389..adfc0033 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt @@ -1,8 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.report.Report import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection import java.nio.file.Path import java.nio.file.Paths @@ -10,20 +10,24 @@ import java.nio.file.Paths class JiraLogs : PostInstallHook { override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { - listOf( - "${jira.home.path}/log/atlassian-jira.log", - "${jira.installation.path}/logs/catalina.out" - ) - .onEach { ensureFile(Paths.get(it), ssh) } - .map { StaticReport(it) } - .forEach { reports.add(it, jira.host) } + reports.add(report(jira), jira.host) } - private fun ensureFile( - path: Path, - ssh: SshConnection - ) { - ssh.execute("mkdir -p ${path.parent!!}") - ssh.execute("touch $path") + fun report(jira: InstalledJira): Report { + return JiraLogsReport(jira) + } + + private class JiraLogsReport(private val jira: InstalledJira) : Report { + override fun locate(ssh: SshConnection): List { + return listOf( + "${jira.home.path}/log/atlassian-jira.log", + "${jira.installation.path}/logs/catalina.out" + ).onEach { ensureFile(Paths.get(it), ssh) } + } + + private fun ensureFile(path: Path, ssh: SshConnection) { + ssh.execute("mkdir -p ${path.parent!!}") + ssh.execute("touch $path") + } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index 89c12a00..d0dcd229 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.JiraLogs import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira @@ -18,59 +19,71 @@ class RestUpgrade( override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val threadDump = ThreadDump(jira.pid, jira.installed.jdk) - val ip = jira.installed.host.privateIp - val port = jira.installed.host.port - val upgradesEndpoint = URI("http://$adminUsername:$adminPassword@$ip:$port/rest/api/2/upgrade") - reports.add(FileListing("thread-dumps/*"), jira.installed.host) - waitForStatusToChange( - statusQuo = "000", - timeout = timeouts.offlineTimeout, - ssh = ssh, - uri = upgradesEndpoint, - threadDump = threadDump - ) - waitForStatusToChange( - statusQuo = "503", - timeout = timeouts.initTimeout, - ssh = ssh, - uri = upgradesEndpoint, - threadDump = threadDump - ) - ssh.execute( - cmd = "curl --silent --retry 6 -X POST $upgradesEndpoint", - timeout = Duration.ofSeconds(15) - ) - waitForStatusToChange( - statusQuo = "303", - timeout = timeouts.upgradeTimeout, - ssh = ssh, - uri = upgradesEndpoint, - threadDump = threadDump - ) + val polling = Upgrades(ssh, jira, adminUsername, adminPassword, timeouts, threadDump, reports) + polling.waitUntilOnline() + polling.waitUntilHealthy() + polling.triggerUpgrades() + polling.waitUntilUpgraded() } - private fun waitForStatusToChange( - statusQuo: String, - uri: URI, - timeout: Duration, - ssh: SshConnection, - threadDump: ThreadDump + private class Upgrades( + private val ssh: SshConnection, + private val jira: StartedJira, + adminUsername: String, + adminPassword: String, + private val timeouts: JiraLaunchTimeouts, + private val threadDump: ThreadDump, + private val reports: Reports ) { - val backoff = Duration.ofSeconds(10) - val deadline = Instant.now() + timeout - while (true) { - val currentStatus = ssh.safeExecute( - cmd = "curl --silent --write-out '%{http_code}' --output /dev/null -X GET $uri", - timeout = timeouts.unresponsivenessTimeout - ).output - if (currentStatus != statusQuo) { - break - } - if (deadline < Instant.now()) { - throw Exception("$uri failed to get out of $statusQuo status within $timeout") + private val upgradesEndpoint: URI + + init { + val ip = jira.installed.host.privateIp + val port = jira.installed.host.port + upgradesEndpoint = URI("http://$adminUsername:$adminPassword@$ip:$port/rest/api/2/upgrade") + } + + fun waitUntilOnline() { + waitForStatusToChange("000", timeouts.offlineTimeout) + } + + fun waitUntilHealthy() { + waitForStatusToChange("503", timeouts.initTimeout) + } + + fun waitUntilUpgraded() { + waitForStatusToChange("303", timeouts.upgradeTimeout) + } + + private fun waitForStatusToChange( + statusQuo: String, + timeout: Duration + ) { + val backoff = Duration.ofSeconds(10) + val deadline = Instant.now() + timeout + while (true) { + val currentStatus = ssh.safeExecute( + cmd = "curl --silent --write-out '%{http_code}' --output /dev/null -X GET $upgradesEndpoint", + timeout = timeouts.unresponsivenessTimeout + ).output + if (currentStatus != statusQuo) { + break + } + if (deadline < Instant.now()) { + reports.add(JiraLogs().report(jira.installed), jira.installed.host) + reports.add(FileListing("thread-dumps/*"), jira.installed.host) + throw Exception("$upgradesEndpoint failed to get out of $statusQuo status within $timeout") + } + threadDump.gather(ssh, "thread-dumps") + Thread.sleep(backoff.toMillis()) } - threadDump.gather(ssh, "thread-dumps") - Thread.sleep(backoff.toMillis()) + } + + fun triggerUpgrades() { + ssh.execute( + cmd = "curl --silent --retry 6 -X POST $upgradesEndpoint", + timeout = Duration.ofSeconds(15) + ) } } -} +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index dc335b9b..7de06cda 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -10,11 +10,14 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreI import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK +import com.atlassian.performance.tools.io.api.resolveSafely import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before import org.junit.Test import java.nio.file.Files +import java.nio.file.Paths +import java.time.Instant class JiraServerPlanIT { @@ -55,7 +58,15 @@ class JiraServerPlanIT { .build() // when - val jiraServer = jiraServerPlan.materialize() + val jiraServer = try { + jiraServerPlan.materialize() + } catch (e: Exception) { + val debugging = Paths.get("build/test-artifacts/") + .resolveSafely(javaClass.simpleName) + .resolveSafely(Instant.now().toString()) + jiraServerPlan.report().downloadTo(debugging) + throw Exception("Jira Server plan failed to materialize, debugging info available in $debugging", e) + } val theNode = jiraServer.nodes.single() val host = theNode.installed.host @@ -76,7 +87,6 @@ class JiraServerPlanIT { .toList() assertThat(fileTree.map { it.toString() }).contains( "jira-node/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", - "jira-node/root/thread-dumps", "jira-node/root/~/jpt-jstat.log", "jira-node/root/~/jpt-vmstat.log", "jira-node/root/~/jpt-iostat.log" From 93a69e5056dfc7ad74182f4d6dfb0f4edbe446ee Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 25 Jun 2021 15:05:05 +0200 Subject: [PATCH 38/73] JPERF-273: Expose NFS or Samba shared homes for DC --- CHANGELOG.md | 1 + .../jira/instance/DefaultClusterProperties.kt | 18 +++++++++++++++ .../api/jira/instance/JiraDataCenterPlan.kt | 23 ++++++++++++++----- .../NfsSharedHome.kt} | 14 +++++------ .../SambaSharedHome.kt} | 14 +++++------ .../jira/instance/ClusterProperties.kt | 13 +++++++++++ .../jira/sharedhome/SharedHomeProperty.kt | 14 +++++++++++ .../api/jira/instance/JiraDataCenterPlanIT.kt | 15 ++++++++---- 8 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/{instance/NfsSharedHomeHook.kt => sharedhome/NfsSharedHome.kt} (86%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/{instance/SambaSharedHomeHook.kt => sharedhome/SambaSharedHome.kt} (89%) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/instance/ClusterProperties.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/sharedhome/SharedHomeProperty.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e392227..64c85ccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -197,6 +197,7 @@ Fix [JPERF-273]: - Hook into Jira start via `PreStartHooks` and `PostStartHooks`. - Let hooks insert new hooks. - Locate and download any logs, charts, profiles and other reports via `Report` (rather than hardcoding the paths). +- Expose preset `NfsSharedHome` or `SambaSharedHome` for Data Center. [JPERF-273]: https://ecosystem.atlassian.net/browse/JPERF-273 diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt new file mode 100644 index 00000000..1e2bbbb3 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt @@ -0,0 +1,18 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.jira.instance.ClusterProperties +import com.atlassian.performance.tools.ssh.api.SshConnection + +class DefaultClusterProperties : PostInstallHook { + + override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { + ClusterProperties(jira).apply { + set("jira.node.id", jira.host.name, ssh) + set("ehcache.object.port", "40011", ssh) + } + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 0d1d926c..2e2057a2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -2,10 +2,12 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancerPlan import java.net.URI @@ -13,7 +15,7 @@ import java.time.Duration import kotlin.streams.asStream import kotlin.streams.toList -class JiraDataCenterPlan constructor( +class JiraDataCenterPlan private constructor( private val nodePlans: List, private val instanceHooks: PreInstanceHooks, private val balancerPlan: LoadBalancerPlan, @@ -74,10 +76,19 @@ class JiraDataCenterPlan constructor( class Builder( private var infrastructure: Infrastructure ) { - private var nodePlans: List = listOf(1, 2).map { JiraNodePlan.Builder().build() } -// TODO private var instanceHooks: PreInstanceHooks = -// PreInstanceHooks(listOf(1..2).map { PreInstallHooks.default() }) // TODO two lists in sync? gotta be a better way -// -// fun build(): Supplier = JiraDataCenterPlan(nodePlans, infrastructure) + private var nodePlans: List = listOf(1, 2).map { + JiraNodePlan.Builder() + .hooks(PreInstallHooks.default().apply { postInstall.insert(DefaultClusterProperties()) }) + .build() + } + private var instanceHooks: PreInstanceHooks = PreInstanceHooks.default() + private var balancerPlan: LoadBalancerPlan = ApacheProxyPlan(infrastructure) + + fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } + fun nodePlans(nodePlans: List) = apply { this.nodePlans = nodePlans } + fun instanceHooks(instanceHooks: PreInstanceHooks) = apply { this.instanceHooks = instanceHooks } + fun balancerPlan(balancerPlan: LoadBalancerPlan) = apply { this.balancerPlan = balancerPlan } + + fun build(): JiraInstancePlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt similarity index 86% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt index 467af37c..cded91ed 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/NfsSharedHomeHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource @@ -6,12 +6,15 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.Installed import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.os.RemotePath import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty import com.atlassian.performance.tools.ssh.api.SshConnection -internal class NfsSharedHomeHook( +class NfsSharedHome( private val jiraHomeSource: JiraHomeSource, private val infrastructure: Infrastructure ) : PreInstanceHook { @@ -52,11 +55,8 @@ internal class NfsSharedHomeHook( ssh.execute("mkdir -p $mountTarget") ssh.execute("sudo mount -o soft,intr,rsize=8192,wsize=8192 $mountSource $mountTarget") ssh.execute("sudo chown ubuntu:ubuntu $mountTarget") - val mountedPath = "`realpath $mountTarget`" - val jiraHome = jira.home.path - ssh.execute("echo ehcache.object.port = 40011 >> $jiraHome/cluster.properties") - ssh.execute("echo jira.node.id = ${jira.host.name} >> $jiraHome/cluster.properties") - ssh.execute("echo jira.shared.home = $mountedPath >> $jiraHome/cluster.properties") + val mounted = "`realpath $mountTarget`" + SharedHomeProperty(jira).set(mounted, ssh) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt similarity index 89% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt index 4406fe05..f98a4757 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/SambaSharedHomeHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource @@ -7,12 +7,15 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty import com.atlassian.performance.tools.ssh.api.SshConnection import java.util.* -internal class SambaSharedHomeHook( +class SambaSharedHome( private val jiraHomeSource: JiraHomeSource, private val infrastructure: Infrastructure ) : PreInstanceHook { @@ -76,11 +79,8 @@ internal class SambaSharedHomeHook( val localUser = ssh.execute("whoami").output.trim() ssh.execute("sudo chown $localUser:$localUser $mountTarget") ssh.execute("sudo mount -t cifs -o $credentials $mountSource $mountTarget") - val sharedHome = "`realpath $mountTarget`" - val nodeHome = jira.home.path - ssh.execute("echo ehcache.object.port = 40011 >> $nodeHome/cluster.properties") - ssh.execute("echo jira.node.id = ${jira.host.name} >> $nodeHome/cluster.properties") - ssh.execute("echo jira.shared.home = $sharedHome >> $nodeHome/cluster.properties") + val mounted = "`realpath $mountTarget`" + SharedHomeProperty(jira).set(mounted, ssh) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/instance/ClusterProperties.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/instance/ClusterProperties.kt new file mode 100644 index 00000000..f0a4f310 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/instance/ClusterProperties.kt @@ -0,0 +1,13 @@ +package com.atlassian.performance.tools.infrastructure.jira.instance + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class ClusterProperties( + private val jira: InstalledJira +) { + + fun set(key: String, value: String, ssh: SshConnection) { + ssh.execute("echo '$key = $value' >> ${jira.home.path}/cluster.properties") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/sharedhome/SharedHomeProperty.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/sharedhome/SharedHomeProperty.kt new file mode 100644 index 00000000..d6bda38b --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/sharedhome/SharedHomeProperty.kt @@ -0,0 +1,14 @@ +package com.atlassian.performance.tools.infrastructure.jira.sharedhome + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.jira.instance.ClusterProperties +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class SharedHomeProperty( + private val jira: InstalledJira +) { + + fun set(mounted: String, ssh: SshConnection) { + ClusterProperties(jira).set("jira.shared.home", mounted, ssh) + } +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 3d9dcca7..834b39d7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -9,6 +9,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelI import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.sharedhome.SambaSharedHome import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook @@ -59,9 +60,12 @@ class JiraDataCenterPlanIT { } val instanceHooks = PreInstanceHooks.default() .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } - .also { it.insert(SambaSharedHomeHook(jiraHomeSource, infrastructure)) } - val balancerPlan = ApacheProxyPlan(infrastructure) - val dcPlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) + .also { it.insert(SambaSharedHome(jiraHomeSource, infrastructure)) } + val dcPlan = JiraDataCenterPlan.Builder(infrastructure) + .nodePlans(nodePlans) + .instanceHooks(instanceHooks) + .balancerPlan(ApacheProxyPlan(infrastructure)) + .build() // when val dataCenter = dcPlan.materialize() @@ -106,8 +110,9 @@ class JiraDataCenterPlanIT { .hooks(PreInstallHooks.default().also { it.postStart.insert(FailingHook()) }) .build() } - val balancerPlan = ApacheProxyPlan(infrastructure) - val dcPlan = JiraDataCenterPlan(nodePlans, PreInstanceHooks.default(), balancerPlan, infrastructure) + val dcPlan = JiraDataCenterPlan.Builder(infrastructure) + .nodePlans(nodePlans) + .build() // when val thrown = catchThrowable { From 5ffe8b7e1ce6e46072e7e5371510c5b444445e1a Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 25 Jun 2021 18:53:01 +0200 Subject: [PATCH 39/73] JPERF-273: Support Jiras with an HTTP path --- .../api/jira/install/HttpHost.kt | 19 +++++++++++++++++++ .../api/jira/install/InstalledJira.kt | 4 ++-- .../api/jira/install/JiraInstallation.kt | 6 +++--- .../api/jira/install/ParallelInstallation.kt | 6 +++--- .../jira/install/SequentialInstallation.kt | 6 +++--- .../jira/install/hook/AsyncProfilerHook.kt | 4 ++-- .../api/jira/install/hook/JiraLogs.kt | 2 +- .../api/jira/install/hook/JvmConfig.kt | 4 ++-- .../jira/install/hook/LateUbuntuSysstat.kt | 2 +- .../api/jira/install/hook/PreInstallHook.kt | 6 +++--- .../api/jira/install/hook/SystemLog.kt | 4 ++-- .../jira/instance/DefaultClusterProperties.kt | 2 +- .../api/jira/instance/JiraServerPlan.kt | 2 +- .../infrastructure/api/jira/report/Reports.kt | 17 ++++++++++++----- .../api/jira/start/hook/AccessLogs.kt | 2 +- .../api/jira/start/hook/JstatHook.kt | 2 +- .../api/jira/start/hook/RestUpgrade.kt | 16 +++++++--------- .../install/hook/HookedJiraInstallation.kt | 10 +++++----- .../jira/install/hook/ProfilerHook.kt | 2 +- .../jira/install/hook/SplunkForwarderHook.kt | 2 +- .../jira/start/hook/HookedJiraStart.kt | 4 ++-- .../jira/install/hook/PreInstallHooksTest.kt | 4 ++-- .../api/jira/instance/JiraDataCenterPlanIT.kt | 4 ++-- .../api/jira/instance/JiraServerPlanIT.kt | 6 ++---- .../api/profiler/AsyncProfilerIT.kt | 4 ++-- 25 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt new file mode 100644 index 00000000..429e51cc --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt @@ -0,0 +1,19 @@ +package com.atlassian.performance.tools.infrastructure.api.jira.install + +import java.net.URI + +class HttpHost internal constructor( + val tcp: TcpHost, + private val basePath: String, + private val supportsTls: Boolean +) { + + fun addressPublicly(): URI = address(tcp.publicIp) + fun addressPrivately(): URI = address(tcp.privateIp) + fun addressPrivately(userName: String, password: String): URI = address(tcp.privateIp, "$userName:$password@") + + private fun address(ip: String, userInfo: String = ""): URI { + val scheme = if (supportsTls) "https" else "http" + return URI("$scheme://$userInfo$ip:${tcp.port}$basePath/") + } +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt index 95c77249..4927bc38 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt @@ -22,7 +22,7 @@ class InstalledJira( */ val jdk: JavaDevelopmentKit, /** - * Hosts Jira. Specifies sockets used by Jira to handle requests. + * Connects to Jira on HTTP level or below. */ - val host: TcpHost + val http: HttpHost ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index deb4bfb0..299a6882 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -10,13 +10,13 @@ import net.jcip.annotations.ThreadSafe interface JiraInstallation { /** - * Installs Jira on [host]. + * Installs Jira on [tcp]. * - * @param [host] will host the Jira + * @param [tcp] will host the Jira * @param [reports] accumulates reports */ fun install( - host: TcpHost, + tcp: TcpHost, reports: Reports ): InstalledJira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index 452f1bea..7bb6a7dd 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -16,10 +16,10 @@ class ParallelInstallation( ) : JiraInstallation { override fun install( - host: TcpHost, + tcp: TcpHost, reports: Reports ): InstalledJira { - host.ssh.newConnection().use { ssh -> + tcp.ssh.newConnection().use { ssh -> val pool = Executors.newCachedThreadPool { runnable -> Thread(runnable, "jira-installation-${runnable.hashCode()}") } @@ -32,7 +32,7 @@ class ParallelInstallation( val java = pool.submitWithLogContext("java") { jdk.also { it.install(ssh) } } - val jira = InstalledJira(home.get(), product.get(), java.get(), host) + val jira = InstalledJira(home.get(), product.get(), java.get(), HttpHost(tcp, "", false)) pool.shutdownNow() return jira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt index c5d124d3..3fa86766 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/SequentialInstallation.kt @@ -14,14 +14,14 @@ class SequentialInstallation( ) : JiraInstallation { override fun install( - host: TcpHost, + tcp: TcpHost, reports: Reports ): InstalledJira { - host.ssh.newConnection().use { ssh -> + tcp.ssh.newConnection().use { ssh -> val installation = productDistribution.installRemotely(ssh, ".") val home = jiraHomeSource.downloadRemotely(ssh) jdk.install(ssh) - return InstalledJira(home, installation, jdk, host) + return InstalledJira(home, installation, jdk, HttpHost(tcp, "", false)) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt index 186453e7..ef86eafc 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt @@ -13,7 +13,7 @@ class AsyncProfilerHook : PreInstallHook { override fun call( ssh: SshConnection, - host: TcpHost, + tcp: TcpHost, hooks: PreInstallHooks, reports: Reports ) { @@ -43,7 +43,7 @@ private class InstalledAsyncProfiler( ) { ssh.execute("$profilerPath -b 20000000 start ${jira.pid}") val profiler = StartedAsyncProfiler(jira.pid, profilerPath) - reports.add(profiler, jira.installed.host) + reports.add(profiler, jira) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt index adfc0033..7d544f19 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt @@ -10,7 +10,7 @@ import java.nio.file.Paths class JiraLogs : PostInstallHook { override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { - reports.add(report(jira), jira.host) + reports.add(report(jira), jira) } fun report(jira: InstalledJira): Report { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt index 88ed1e91..3fe4ab97 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt @@ -23,9 +23,9 @@ class JvmConfig( connection = ssh, config = config, gcLog = gcLog, - jiraIp = jira.host.publicIp + jiraIp = jira.http.tcp.publicIp ) val report = FileListing(gcLog.path("*")) - reports.add(report, jira.host) + reports.add(report, jira) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt index 26f327e2..2404e567 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt @@ -32,6 +32,6 @@ private class PostStartOsMetric( ) : PostStartHook { override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val process = metric.start(ssh) - reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) + reports.add(RemoteMonitoringProcessReport(process), jira) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt index b9be4a39..ec5f329f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt @@ -10,14 +10,14 @@ import com.atlassian.performance.tools.ssh.api.SshConnection interface PreInstallHook { /** - * @param [ssh] connects to the [host] - * @param [host] will install Jira + * @param [ssh] connects to the [tcp] + * @param [tcp] will install Jira * @param [hooks] inserts future hooks * @param [reports] accumulates reports */ fun call( ssh: SshConnection, - host: TcpHost, + tcp: TcpHost, hooks: PreInstallHooks, reports: Reports ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt index 235e41d2..28084dfa 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt @@ -7,7 +7,7 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class SystemLog : PreInstallHook { - override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks, reports: Reports) { - reports.add(FileListing("/var/log/syslog"), host) + override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { + reports.add(FileListing("/var/log/syslog"), tcp) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt index 1e2bbbb3..ab342f07 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt @@ -11,7 +11,7 @@ class DefaultClusterProperties : PostInstallHook { override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { ClusterProperties(jira).apply { - set("jira.node.id", jira.host.name, ssh) + set("jira.node.id", jira.http.tcp.name, ssh) set("ehcache.object.port", "40011", ssh) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index c9d7da75..d15eaa0a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -30,7 +30,7 @@ class JiraServerPlan private constructor( private class JiraServer( node: StartedJira ) : JiraInstance { - override val address: URI = node.installed.host.run { URI("http://$publicIp:$port/") } + override val address: URI = node.installed.http.addressPublicly() override val nodes: List = listOf(node) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index 84aa3ae9..76a7b1c4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -1,6 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.report +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.os.RemotePath import com.atlassian.performance.tools.io.api.ensureDirectory import com.atlassian.performance.tools.io.api.resolveSafely @@ -15,11 +17,16 @@ class Reports private constructor( // TODO turn into SPI to allow AWS CLI transp ) { constructor() : this(ConcurrentLinkedQueue()) - fun add( - report: Report, - host: TcpHost - ) { - hostReports.add(HostReport(host, report)) + fun add(report: Report, started: StartedJira) { + add(report, started.installed) + } + + fun add(report: Report, installed: InstalledJira) { + add(report, installed.http.tcp) + } + + fun add(report: Report, tcp: TcpHost) { + hostReports.add(HostReport(tcp, report)) } fun downloadTo( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt index f6f35c5d..c2c30a78 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt @@ -8,6 +8,6 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class AccessLogs : PreStartHook { override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PreStartHooks, reports: Reports) { - reports.add(FileListing("${jira.installation.path}/logs/*access*"), jira.host) + reports.add(FileListing("${jira.installation.path}/logs/*access*"), jira) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt index 547e51af..f1e15be5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt @@ -14,6 +14,6 @@ class JstatHook : PostStartHook { reports: Reports ) { val process = jira.installed.jdk.jstatMonitoring.start(ssh, jira.pid) - reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) + reports.add(RemoteMonitoringProcessReport(process), jira) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index d0dcd229..e9e3b9b5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -35,13 +35,11 @@ class RestUpgrade( private val threadDump: ThreadDump, private val reports: Reports ) { - private val upgradesEndpoint: URI - - init { - val ip = jira.installed.host.privateIp - val port = jira.installed.host.port - upgradesEndpoint = URI("http://$adminUsername:$adminPassword@$ip:$port/rest/api/2/upgrade") - } + private val upgradesEndpoint: URI = jira + .installed + .http + .addressPrivately(adminUsername, adminPassword) + .resolve("rest/api/2/upgrade") fun waitUntilOnline() { waitForStatusToChange("000", timeouts.offlineTimeout) @@ -70,8 +68,8 @@ class RestUpgrade( break } if (deadline < Instant.now()) { - reports.add(JiraLogs().report(jira.installed), jira.installed.host) - reports.add(FileListing("thread-dumps/*"), jira.installed.host) + reports.add(JiraLogs().report(jira.installed), jira) + reports.add(FileListing("thread-dumps/*"), jira) throw Exception("$upgradesEndpoint failed to get out of $statusQuo status within $timeout") } threadDump.gather(ssh, "thread-dumps") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt index 153fafe8..ba8b8cc7 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt @@ -12,14 +12,14 @@ class HookedJiraInstallation( ) : JiraInstallation { override fun install( - host: TcpHost, + tcp: TcpHost, reports: Reports ): InstalledJira { - host.ssh.newConnection().use { ssh -> - hooks.call(ssh, host, reports) + tcp.ssh.newConnection().use { ssh -> + hooks.call(ssh, tcp, reports) } - val installed = installation.install(host, reports) - host.ssh.newConnection().use { ssh -> + val installed = installation.install(tcp, reports) + tcp.ssh.newConnection().use { ssh -> hooks.postInstall.call(ssh, installed, reports) } return installed diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt index 294ab3e5..3ecd6098 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt @@ -37,7 +37,7 @@ private class InstalledProfiler( ) { val process = profiler.start(ssh, jira.pid) if (process != null) { - reports.add(RemoteMonitoringProcessReport(process), jira.installed.host) + reports.add(RemoteMonitoringProcessReport(process), jira) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt index 1e27f25b..0baf1797 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt @@ -18,6 +18,6 @@ internal class SplunkForwarderHook( reports: Reports ) { splunk.jsonifyLog4j(ssh, "${jira.installation.path}/atlassian-jira/WEB-INF/classes/log4j.properties") - splunk.run(ssh, jira.host.name, "/home/ubuntu/jirahome/log") + splunk.run(ssh, jira.http.tcp.name, "/home/ubuntu/jirahome/log") } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt index e23395f9..73d02676 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt @@ -15,11 +15,11 @@ class HookedJiraStart( installed: InstalledJira, reports: Reports ): StartedJira { - installed.host.ssh.newConnection().use { ssh -> + installed.http.tcp.ssh.newConnection().use { ssh -> hooks.call(ssh, installed, reports) } val started = start.start(installed, reports) - installed.host.ssh.newConnection().use { ssh -> + installed.http.tcp.ssh.newConnection().use { ssh -> hooks.postStart.call(ssh, started, reports) } return started diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index 711dec3b..2ddfb10c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -48,7 +48,7 @@ private class CountingHook : PreInstallHook { var count = 0 - override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks, reports: Reports) { + override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { count++ } } @@ -56,7 +56,7 @@ private class CountingHook : PreInstallHook { private class InsertingHook( private val hook: PreInstallHook ) : PreInstallHook { - override fun call(ssh: SshConnection, host: TcpHost, hooks: PreInstallHooks, reports: Reports) { + override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { hooks.insert(hook) } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 834b39d7..50e91343 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -77,9 +77,9 @@ class JiraDataCenterPlanIT { .installation .resolve("conf/server.xml") .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" + installed.http.tcp.ssh.newConnection().use { ssh -> ssh.execute("wget ${dataCenter.address}") } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 7de06cda..3c944099 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -67,18 +67,16 @@ class JiraServerPlanIT { jiraServerPlan.report().downloadTo(debugging) throw Exception("Jira Server plan failed to materialize, debugging info available in $debugging", e) } - - val theNode = jiraServer.nodes.single() - val host = theNode.installed.host val reports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) // then + val theNode = jiraServer.nodes.single() val serverXml = theNode .installed .installation .resolve("conf/server.xml") .download(Files.createTempFile("downloaded-config", ".xml")) - assertThat(serverXml.readText()).contains(" - installedJira.host.ssh.newConnection().use { ssh -> + installedJira.http.tcp.ssh.newConnection().use { ssh -> // when profiler.install(ssh) val startedJira = JiraLaunchScript().start(installedJira, Reports()) @@ -41,7 +41,7 @@ class AsyncProfilerIT { process.stop(ssh) // then - val profilerResult = RemotePath(installedJira.host.ssh.host, process.getResultPath()) + val profilerResult = RemotePath(installedJira.http.tcp.ssh.host, process.getResultPath()) .download(createTempFile("profiler-result", ".svg")) assertThat(profilerResult.readLines().take(5)).contains("") } From 0c677142e6f2f09e0eca7b75220993f7bc20b3c6 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 25 Jun 2021 18:53:40 +0200 Subject: [PATCH 40/73] JPERF-273: Check Jira HTML when upgrade fails --- .../api/jira/start/hook/RestUpgrade.kt | 2 ++ .../jira/report/JiraLandingPage.kt | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/JiraLandingPage.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt index e9e3b9b5..3762f7d2 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt @@ -6,6 +6,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListin import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jvm.ThreadDump +import com.atlassian.performance.tools.infrastructure.jira.report.JiraLandingPage import com.atlassian.performance.tools.ssh.api.SshConnection import java.net.URI import java.time.Duration @@ -70,6 +71,7 @@ class RestUpgrade( if (deadline < Instant.now()) { reports.add(JiraLogs().report(jira.installed), jira) reports.add(FileListing("thread-dumps/*"), jira) + reports.add(JiraLandingPage(jira), jira) throw Exception("$upgradesEndpoint failed to get out of $statusQuo status within $timeout") } threadDump.gather(ssh, "thread-dumps") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/JiraLandingPage.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/JiraLandingPage.kt new file mode 100644 index 00000000..8d0b1302 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/report/JiraLandingPage.kt @@ -0,0 +1,19 @@ +package com.atlassian.performance.tools.infrastructure.jira.report + +import com.atlassian.performance.tools.infrastructure.api.jira.report.Report +import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.ssh.api.SshConnection + +internal class JiraLandingPage( + private val started: StartedJira +) : Report { + override fun locate(ssh: SshConnection): List { + Ubuntu().install(ssh, listOf("curl")) + val landingPage = started.installed.http.addressPrivately() + val html = "jira-landing-page.html" + val headers = "jira-landing-page-headers.txt" + ssh.execute("curl $landingPage --location --output $html --dump-header $headers --silent") + return listOf(html, headers) + } +} From 014b58015d3fcd34ca75e97a57fedec7f64ee566 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 28 Jun 2021 10:09:25 +0200 Subject: [PATCH 41/73] More time for Jira plugins on GHA --- .../com/atlassian/performance/tools/infrastructure/Datasets.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 5c3fb0cb..ed65cf1f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -34,7 +34,7 @@ class Datasets { fun hookMysql(postStartHooks: PostStartHooks) { val timeouts = JiraLaunchTimeouts.Builder() - .initTimeout(Duration.ofSeconds(45)) + .initTimeout(Duration.ofMinutes(2)) .build() val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") postStartHooks.insert(dataUpgrade) From 0d15ed524d4af362eafefc3cd38d735148190581 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 28 Jun 2021 12:32:53 +0200 Subject: [PATCH 42/73] Give even more time for Jira plugins on GHA --- .../com/atlassian/performance/tools/infrastructure/Datasets.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index ed65cf1f..0363e416 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -34,7 +34,7 @@ class Datasets { fun hookMysql(postStartHooks: PostStartHooks) { val timeouts = JiraLaunchTimeouts.Builder() - .initTimeout(Duration.ofMinutes(2)) + .initTimeout(Duration.ofMinutes(4)) .build() val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") postStartHooks.insert(dataUpgrade) From 7fabda3b69a4c3da22ae3744993c4b1a645ba0da Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 2 Jul 2021 17:44:46 +0200 Subject: [PATCH 43/73] Clarify what `JiraNodePlan` does and doesn't do Some architectural answers: * `JiraInstancePlan`, `JiraNodePlan`, `JiraInstallation`, `JiraStart`, are all lightweight plans without any resources * `HttpNode`, `InstalledJira`, `StartedJira`, `JiraInstance` are all resources without any plans * plans are independent from each other and don't talk, even through resources Open questions: * same as previous commit: who controls the ports? `ParallelInstallation` has run into trouble when it ignored the factual `HttpNode` it received --- .../infrastructure/api/Infrastructure.kt | 10 ++-- .../api/database/DockerMysqlServer.kt | 4 +- .../jira/install/{HttpHost.kt => HttpNode.kt} | 4 +- .../api/jira/install/InstalledJira.kt | 2 +- .../api/jira/install/JiraInstallation.kt | 6 +-- .../api/jira/install/ParallelInstallation.kt | 7 +-- .../jira/install/SequentialInstallation.kt | 6 +-- .../jira/install/{TcpHost.kt => TcpNode.kt} | 2 +- .../jira/install/hook/AsyncProfilerHook.kt | 4 +- .../api/jira/install/hook/PreInstallHook.kt | 9 ++-- .../api/jira/install/hook/PreInstallHooks.kt | 6 +-- .../api/jira/install/hook/SystemLog.kt | 6 +-- .../api/jira/instance/JiraDataCenterPlan.kt | 50 +++++++++---------- .../jira/{node => instance}/JiraNodePlan.kt | 26 +++++++--- .../api/jira/instance/JiraServerPlan.kt | 13 ++--- .../infrastructure/api/jira/node/JiraNode.kt | 8 --- .../infrastructure/api/jira/report/Reports.kt | 13 +++-- .../api/jira/sharedhome/SambaSharedHome.kt | 4 +- .../api/jira/start/JiraStart.kt | 3 ++ .../api/loadbalancer/ApacheProxyPlan.kt | 22 ++++---- .../api/loadbalancer/LoadBalancerPlan.kt | 5 +- .../tools/infrastructure/database/MySql.kt | 4 +- .../install/hook/HookedJiraInstallation.kt | 12 ++--- .../api/DockerInfrastructure.kt | 23 ++++++--- .../jira/install/hook/PreInstallHooksTest.kt | 17 ++++--- .../api/jira/instance/JiraDataCenterPlanIT.kt | 5 +- .../api/jira/instance/JiraServerPlanIT.kt | 25 +++++++--- .../api/profiler/AsyncProfilerIT.kt | 4 +- 28 files changed, 168 insertions(+), 132 deletions(-) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/{HttpHost.kt => HttpNode.kt} (91%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/{TcpHost.kt => TcpNode.kt} (96%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/{node => instance}/JiraNodePlan.kt (70%) delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt index 06de898f..82b1fdfe 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.ssh.api.Ssh interface Infrastructure : AutoCloseable { // TODO rename to ServerRoom @@ -8,9 +9,10 @@ interface Infrastructure : AutoCloseable { // TODO rename to ServerRoom val subnet: String /** - * @return can be reached by the caller via [TcpHost.publicIp] and by the rest of the infra via [TcpHost.privateIp] + * @return can be reached by the caller via [TcpNode.publicIp] and by the rest of the infra via [TcpNode.privateIp] */ - fun serveTcp(name: String): TcpHost - fun serve(name: String, tcpPorts: List, udpPorts: List): TcpHost + fun serveTcp(name: String): TcpNode + fun serveHttp(name: String): HttpNode + fun serve(name: String, tcpPorts: List, udpPorts: List): TcpNode fun serveSsh(name: String): Ssh } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 247aef8c..4f1bc6dc 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.database import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.* import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports @@ -33,7 +33,7 @@ class DockerMysqlServer private constructor( hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) } - private fun setup(ssh: SshConnection, server: TcpHost): SshSqlClient { + private fun setup(ssh: SshConnection, server: TcpNode): SshSqlClient { val mysqlDataLocation = source.download(ssh) val containerName = Mysql.container( dataDir = mysqlDataLocation, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt similarity index 91% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt index 429e51cc..d4636e21 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt @@ -2,8 +2,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install import java.net.URI -class HttpHost internal constructor( - val tcp: TcpHost, +class HttpNode internal constructor( + val tcp: TcpNode, private val basePath: String, private val supportsTls: Boolean ) { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt index 4927bc38..92dd76c3 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/InstalledJira.kt @@ -24,5 +24,5 @@ class InstalledJira( /** * Connects to Jira on HTTP level or below. */ - val http: HttpHost + val http: HttpNode ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt index 299a6882..d34f1a76 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/JiraInstallation.kt @@ -10,13 +10,13 @@ import net.jcip.annotations.ThreadSafe interface JiraInstallation { /** - * Installs Jira on [tcp]. + * Installs Jira on [http] node. * - * @param [tcp] will host the Jira + * @param [http] will host the Jira * @param [reports] accumulates reports */ fun install( - tcp: TcpHost, + http: HttpNode, reports: Reports ): InstalledJira } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index 7bb6a7dd..ec81eb86 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -16,10 +16,10 @@ class ParallelInstallation( ) : JiraInstallation { override fun install( - tcp: TcpHost, + http: HttpNode, reports: Reports ): InstalledJira { - tcp.ssh.newConnection().use { ssh -> + http.tcp.ssh.newConnection().use { ssh -> val pool = Executors.newCachedThreadPool { runnable -> Thread(runnable, "jira-installation-${runnable.hashCode()}") } @@ -32,7 +32,8 @@ class ParallelInstallation( val java = pool.submitWithLogContext("java") { jdk.also { it.install(ssh) } } - val jira = InstalledJira(home.get(), product.get(), java.get(), HttpHost(tcp, "", false)) + TODO("${http.tcp.privateIp} is ignored and `InstalledJira.installation.resolve('server.xml')` still hardcodes ` + http.tcp.ssh.newConnection().use { ssh -> val installation = productDistribution.installRemotely(ssh, ".") val home = jiraHomeSource.downloadRemotely(ssh) jdk.install(ssh) - return InstalledJira(home, installation, jdk, HttpHost(tcp, "", false)) + return InstalledJira(home, installation, jdk, http) } } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpNode.kt similarity index 96% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpNode.kt index 5c06e3f8..a69e756a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpHost.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/TcpNode.kt @@ -7,7 +7,7 @@ import com.atlassian.performance.tools.ssh.api.Ssh * @param [ssh] connects to the host via [publicIp] * @param [port] accepts connections at within the [privateIp] network */ -class TcpHost( +class TcpNode( val publicIp: String, val privateIp: String, val port: Int, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt index ef86eafc..453ba963 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Report import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira @@ -13,7 +13,7 @@ class AsyncProfilerHook : PreInstallHook { override fun call( ssh: SshConnection, - tcp: TcpHost, + http: HttpNode, hooks: PreInstallHooks, reports: Reports ) { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt index ec5f329f..6998f149 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt @@ -1,8 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection +import org.apache.http.HttpHost /** * Intercepts a call before Jira is installed. @@ -10,14 +11,14 @@ import com.atlassian.performance.tools.ssh.api.SshConnection interface PreInstallHook { /** - * @param [ssh] connects to the [tcp] - * @param [tcp] will install Jira + * @param [ssh] connects to the [http] host + * @param [http] will install Jira * @param [hooks] inserts future hooks * @param [reports] accumulates reports */ fun call( ssh: SshConnection, - tcp: TcpHost, + http: HttpNode, hooks: PreInstallHooks, reports: Reports ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt index 58e256fa..d748580f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt @@ -1,6 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection import java.util.* @@ -22,13 +22,13 @@ class PreInstallHooks private constructor( internal fun call( ssh: SshConnection, - host: TcpHost, + http: HttpNode, reports: Reports ) { while (true) { hooks .poll() - ?.call(ssh, host, this, reports) + ?.call(ssh, http, this, reports) ?: break } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt index 28084dfa..21904606 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt @@ -1,13 +1,13 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection class SystemLog : PreInstallHook { - override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { - reports.add(FileListing("/var/log/syslog"), tcp) + override fun call(ssh: SshConnection, http: HttpNode, hooks: PreInstallHooks, reports: Reports) { + reports.add(FileListing("/var/log/syslog"), http) } } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 2e2057a2..0783d011 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -1,10 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.Infrastructure +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan @@ -18,8 +17,7 @@ import kotlin.streams.toList class JiraDataCenterPlan private constructor( private val nodePlans: List, private val instanceHooks: PreInstanceHooks, - private val balancerPlan: LoadBalancerPlan, - private val infrastructure: Infrastructure + private val balancerPlan: LoadBalancerPlan ) : JiraInstancePlan { private val reports: Reports = Reports() @@ -27,13 +25,13 @@ class JiraDataCenterPlan private constructor( override fun materialize(): JiraInstance { instanceHooks.call(nodePlans.map { it.hooks }, reports) - val nodes = nodePlans.mapIndexed { nodeIndex, nodePlan -> + val http = nodePlans.mapIndexed { nodeIndex, plan -> val nodeNumber = nodeIndex + 1 - val host = infrastructure.serveTcp("jira-node-$nodeNumber") - nodePlan.materialize(host) + val http = plan.infrastructure.serveHttp("jira-node-$nodeNumber") + PlannedHttpNode(http, plan) } - val balancer = balancerPlan.materialize(nodes) - val installed = installInParallel(nodes) + val balancer = balancerPlan.materialize(http.map { it.http }, nodePlans.map { it.hooks.preStart }) + val installed = installInParallel(http) val started = installed.map { it.start(reports) } val instance = JiraDataCenter(started, balancer) instanceHooks.postInstance.call(instance, reports) @@ -43,25 +41,28 @@ class JiraDataCenterPlan private constructor( override fun report(): Reports = reports.copy() - private fun installInParallel(nodes: List) = nodes + private fun installInParallel(nodes: Collection): List = nodes .asSequence() .asStream() .parallel() - .map { jiraNode -> - jiraNode - .plan - .installation - .install(jiraNode.host, reports) - .let { installedJira -> InstalledJiraNode(installedJira, jiraNode.plan) } - } + .map { it.install(reports) } .toList() - private class InstalledJiraNode( - private val installedJira: InstalledJira, - private val nodePlan: JiraNodePlan + private class PlannedHttpNode( + val http: HttpNode, + val plan: JiraNodePlan + ) { + fun install(reports: Reports): PlannedInstalledJira { + return plan.installation.install(http, reports).let { PlannedInstalledJira(it, plan) } + } + } + + private class PlannedInstalledJira( + val installed: InstalledJira, + val plan: JiraNodePlan ) { fun start(reports: Reports): StartedJira { - return nodePlan.start.start(installedJira, reports) + return plan.start.start(installed, reports) } } @@ -74,21 +75,20 @@ class JiraDataCenterPlan private constructor( } class Builder( - private var infrastructure: Infrastructure + infrastructure: Infrastructure ) { private var nodePlans: List = listOf(1, 2).map { - JiraNodePlan.Builder() + JiraNodePlan.Builder(infrastructure) .hooks(PreInstallHooks.default().apply { postInstall.insert(DefaultClusterProperties()) }) .build() } private var instanceHooks: PreInstanceHooks = PreInstanceHooks.default() private var balancerPlan: LoadBalancerPlan = ApacheProxyPlan(infrastructure) - fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } fun nodePlans(nodePlans: List) = apply { this.nodePlans = nodePlans } fun instanceHooks(instanceHooks: PreInstanceHooks) = apply { this.instanceHooks = instanceHooks } fun balancerPlan(balancerPlan: LoadBalancerPlan) = apply { this.balancerPlan = balancerPlan } - fun build(): JiraInstancePlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan, infrastructure) + fun build(): JiraInstancePlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt similarity index 70% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt index d4664efe..594e4696 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNodePlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt @@ -1,10 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.node +package com.atlassian.performance.tools.infrastructure.api.jira.instance +import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart @@ -13,16 +13,26 @@ import com.atlassian.performance.tools.infrastructure.jira.install.hook.HookedJi import com.atlassian.performance.tools.infrastructure.jira.start.hook.HookedJiraStart import net.jcip.annotations.NotThreadSafe +/** + * Specifies how a Jira node should be built. + * Does not build the node, due to various possible ordering, concurrency and optimizations. + * Actual provisioning is reserved for a [JiraInstancePlan]. + * + * @constructor specifies the plan, but doesn't hold any resources + * @see JiraInstancePlan + * @since 4.19.0 + */ class JiraNodePlan private constructor( - val installation: JiraInstallation, - val start: JiraStart, + internal val infrastructure: Infrastructure, + internal val installation: JiraInstallation, + internal val start: JiraStart, internal val hooks: PreInstallHooks ) { - fun materialize(host: TcpHost) = JiraNode(host, this) - @NotThreadSafe - class Builder { + class Builder( + private var infrastructure: Infrastructure + ) { private var installation: JiraInstallation = ParallelInstallation( EmptyJiraHome(), PublicJiraSoftwareDistribution("7.13.0"), @@ -31,11 +41,13 @@ class JiraNodePlan private constructor( private var start: JiraStart = JiraLaunchScript() private var hooks: PreInstallHooks = PreInstallHooks.default() + fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } fun installation(installation: JiraInstallation) = apply { this.installation = installation } fun start(start: JiraStart) = apply { this.start = start } fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } fun build() = JiraNodePlan( + infrastructure, HookedJiraInstallation(installation, hooks), HookedJiraStart(start, hooks.preStart), hooks diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index d15eaa0a..1f819e6d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -1,14 +1,12 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.Infrastructure -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import java.net.URI class JiraServerPlan private constructor( private val plan: JiraNodePlan, - private val infrastructure: Infrastructure, private val hooks: PreInstanceHooks ) : JiraInstancePlan { @@ -17,8 +15,8 @@ class JiraServerPlan private constructor( override fun materialize(): JiraInstance { val nodeHooks = listOf(plan).map { it.hooks } hooks.call(nodeHooks, reports) - val jiraNode = infrastructure.serveTcp("jira-node") - val installed = plan.installation.install(jiraNode, reports) + val http = plan.infrastructure.serveHttp("jira-node") + val installed = plan.installation.install(http, reports) val started = plan.start.start(installed, reports) val instance = JiraServer(started) hooks.postInstance.call(instance, reports) @@ -35,15 +33,14 @@ class JiraServerPlan private constructor( } class Builder( - private var infrastructure: Infrastructure + infrastructure: Infrastructure ) { - private var plan: JiraNodePlan = JiraNodePlan.Builder().build() + private var plan: JiraNodePlan = JiraNodePlan.Builder(infrastructure).build() private var hooks: PreInstanceHooks = PreInstanceHooks.default() fun plan(plan: JiraNodePlan) = apply { this.plan = plan } - fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } fun hooks(hooks: PreInstanceHooks) = apply { this.hooks = hooks } - fun build(): JiraInstancePlan = JiraServerPlan(plan, infrastructure, hooks) + fun build(): JiraInstancePlan = JiraServerPlan(plan, hooks) } } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt deleted file mode 100644 index 3e0edb01..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/node/JiraNode.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.node - -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost - -class JiraNode constructor( - val host: TcpHost, - val plan: JiraNodePlan -) \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index 76a7b1c4..4feca137 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -1,7 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.report +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.os.RemotePath import com.atlassian.performance.tools.io.api.ensureDirectory @@ -22,10 +23,14 @@ class Reports private constructor( // TODO turn into SPI to allow AWS CLI transp } fun add(report: Report, installed: InstalledJira) { - add(report, installed.http.tcp) + add(report, installed.http) } - fun add(report: Report, tcp: TcpHost) { + fun add(report: Report, http: HttpNode) { + hostReports.add(HostReport(http.tcp, report)) + } + + fun add(report: Report, tcp: TcpNode) { hostReports.add(HostReport(tcp, report)) } @@ -60,7 +65,7 @@ class Reports private constructor( // TODO turn into SPI to allow AWS CLI transp } private class HostReport( - val host: TcpHost, + val host: TcpNode, val report: Report ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt index f98a4757..7d364381 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt @@ -3,7 +3,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks @@ -38,7 +38,7 @@ class SambaSharedHome( return sharedHome } - private fun export(ssh: SshConnection, sharedHome: String, server: TcpHost): SambaMount { + private fun export(ssh: SshConnection, sharedHome: String, server: TcpNode): SambaMount { Ubuntu().install(ssh, listOf("samba")) val shareName = "samba-jira-home" val share = """ diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt index 706e01e2..891e000c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/JiraStart.kt @@ -4,6 +4,9 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.Installed import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import net.jcip.annotations.ThreadSafe +/** + * @since 4.19.0 + */ @ThreadSafe interface JiraStart { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt index d0edc217..5704ea7f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -2,9 +2,9 @@ package com.atlassian.performance.tools.infrastructure.api.loadbalancer import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.Sed +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks @@ -21,21 +21,21 @@ class ApacheProxyPlan( private val configPath = "/etc/apache2/sites-enabled/000-default.conf" - override fun materialize(nodes: List): LoadBalancer { - val proxyNode = infrastructure.serveTcp("apache-proxy") + override fun materialize(nodes: List, hooks: List): LoadBalancer { + val proxyNode = infrastructure.serveHttp("apache-proxy") IdempotentAction("Installing and configuring apache load balancer") { - proxyNode.ssh.newConnection().use { connection -> + proxyNode.tcp.ssh.newConnection().use { connection -> tryToProvision(connection, nodes, proxyNode) } }.retry(2, ExponentialBackoff(Duration.ofSeconds(5))) - val balancerEndpoint = URI("http://${proxyNode.privateIp}:${proxyNode.port}/") - nodes.forEach { it.plan.hooks.preStart.insert(InjectProxy(balancerEndpoint)) } + val balancerEndpoint = proxyNode.addressPrivately() + hooks.forEach { it.insert(InjectProxy(balancerEndpoint)) } return ApacheProxy(balancerEndpoint) } - private fun tryToProvision(ssh: SshConnection, nodes: List, proxyNode: TcpHost) { + private fun tryToProvision(ssh: SshConnection, nodes: List, proxyNode: HttpNode) { Ubuntu().install(ssh, listOf("apache2")) - Sed().replace(ssh, "Listen 80", "Listen ${proxyNode.port}", "/etc/apache2/ports.conf") + Sed().replace(ssh, "Listen 80", "Listen ${proxyNode.tcp.port}", "/etc/apache2/ports.conf") ssh.execute("sudo rm $configPath") ssh.execute("sudo touch $configPath") val mods = listOf( @@ -48,8 +48,8 @@ class ApacheProxyPlan( "Header add Set-Cookie \\\"ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/\\\" env=BALANCER_ROUTE_CHANGED" ) appendConfig(ssh, "") - nodes.forEachIndexed { index, node -> - appendConfig(ssh, "\tBalancerMember http://${node.host.privateIp}:${node.host.port} route=$index") + nodes.forEachIndexed { index, http -> + appendConfig(ssh, "\tBalancerMember ${http.addressPrivately()} route=$index") } appendConfig(ssh, "\n") appendConfig(ssh, "ProxyPass / balancer://mycluster/ stickysession=ROUTEID") diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt index a433661b..c0d9cca6 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt @@ -1,7 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.loadbalancer -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode +import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks interface LoadBalancerPlan { - fun materialize(nodes: List): LoadBalancer + fun materialize(nodes: List, hooks: List): LoadBalancer } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index 49fd00bd..1fe0707d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -1,7 +1,7 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.docker.DockerContainer -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.docker.DeadContainerCheck import com.atlassian.performance.tools.jvmtasks.api.Backoff @@ -40,7 +40,7 @@ internal object Mysql { dataDir: String, extraParameters: Array, extraArguments: Array, - host: TcpHost? = null + host: TcpNode? = null ) = DockerContainer.Builder() .imageName("mysql:5.7.32") .pullTimeout(Duration.ofMinutes(5)) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt index ba8b8cc7..89c2ac7d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt @@ -1,8 +1,8 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports @@ -12,14 +12,14 @@ class HookedJiraInstallation( ) : JiraInstallation { override fun install( - tcp: TcpHost, + http: HttpNode, reports: Reports ): InstalledJira { - tcp.ssh.newConnection().use { ssh -> - hooks.call(ssh, tcp, reports) + http.tcp.ssh.newConnection().use { ssh -> + hooks.call(ssh, http, reports) } - val installed = installation.install(tcp, reports) - tcp.ssh.newConnection().use { ssh -> + val installed = installation.install(http, reports) + http.tcp.ssh.newConnection().use { ssh -> hooks.postInstall.call(ssh, installed, reports) } return installed diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index a80e1b6c..e21b1277 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.lib.docker.CreatedContainer import com.atlassian.performance.tools.infrastructure.lib.docker.DockerNetwork import com.atlassian.performance.tools.infrastructure.lib.docker.StartedContainer @@ -55,7 +56,7 @@ internal class DockerInfrastructure( return serveTcp(888, name).ssh } - override fun serveTcp(name: String): TcpHost { + override fun serveTcp(name: String): TcpNode { // TODO pre-provision all the hosts rather than on-demand - unlock batch provisioning (CFN Stack), picking EC2 types, SSD storage, TCP port ranges, subnets, etc. return when { name.startsWith("jira-node") -> serveTcp(8080, name) // TODO this is a contract on undocumented behavior @@ -65,12 +66,20 @@ internal class DockerInfrastructure( } } - private fun serveTcp(tcpPort: Int, name: String): TcpHost { + override fun serveHttp(name: String): HttpNode { + return HttpNode( + serveTcp(80, name), + "/", + false + ) + } + + private fun serveTcp(tcpPort: Int, name: String): TcpNode { return serve(name, listOf(tcpPort), emptyList()) } - override fun serve(name: String, tcpPorts: List, udpPorts: List): TcpHost { + override fun serve(name: String, tcpPorts: List, udpPorts: List): TcpNode { val ports = tcpPorts.map { ExposedPort.tcp(it) } + udpPorts.map { ExposedPort.udp(it) } + ExposedPort.tcp(22) @@ -107,7 +116,7 @@ internal class DockerInfrastructure( created: CreatedContainer, tcpPort: Int, name: String - ): TcpHost { + ): TcpNode { val startedContainer = docker .startContainerCmd(created.response.id) .execAsResource(docker) @@ -119,7 +128,7 @@ internal class DockerInfrastructure( started: StartedContainer, tcpPort: Int, name: String - ): TcpHost { + ): TcpNode { val networkSettings = docker .inspectContainerCmd(started.id) .exec() @@ -141,7 +150,7 @@ internal class DockerInfrastructure( it.execute("apt-get update", Duration.ofMinutes(2)) it.execute("apt-get -y install sudo gnupg screen") } - return TcpHost("localhost", ip, tcpPort, name, ssh) + return TcpNode("localhost", ip, tcpPort, name, ssh) } private fun getHostPort( diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index 2ddfb10c..b94cfca2 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -1,6 +1,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpHost +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.mock.UnimplementedSshConnection import com.atlassian.performance.tools.ssh.api.Ssh @@ -13,7 +14,11 @@ import java.nio.file.Paths class PreInstallHooksTest { private val dummySsh = Ssh(SshHost("localhost", "dummyUser", Paths.get("dummyKey"))) - private val dummyServer = TcpHost("dummyPublicIp", "dummyPrivateIp", 123, "fake-server", dummySsh) + private val dummyHttp = HttpNode( + TcpNode("dummyPublicIp", "dummyPrivateIp", 123, "fake-server", dummySsh), + "/", + false + ) @Test fun shouldInsertDuringListing() { @@ -24,7 +29,7 @@ class PreInstallHooksTest { insert(counter) } - hooks.call(UnimplementedSshConnection(), dummyServer, Reports()) + hooks.call(UnimplementedSshConnection(), dummyHttp, Reports()) assertThat(counter.count).isEqualTo(3) } @@ -38,7 +43,7 @@ class PreInstallHooksTest { insert(InsertingHook(counter)) } - hooks.call(UnimplementedSshConnection(), dummyServer, Reports()) + hooks.call(UnimplementedSshConnection(), dummyHttp, Reports()) assertThat(counter.count).isEqualTo(3) } @@ -48,7 +53,7 @@ private class CountingHook : PreInstallHook { var count = 0 - override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { + override fun call(ssh: SshConnection, http: HttpNode, hooks: PreInstallHooks, reports: Reports) { count++ } } @@ -56,7 +61,7 @@ private class CountingHook : PreInstallHook { private class InsertingHook( private val hook: PreInstallHook ) : PreInstallHook { - override fun call(ssh: SshConnection, tcp: TcpHost, hooks: PreInstallHooks, reports: Reports) { + override fun call(ssh: SshConnection, http: HttpNode, hooks: PreInstallHooks, reports: Reports) { hooks.insert(hook) } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 50e91343..8171c21b 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -7,7 +7,6 @@ import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJir import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.sharedhome.SambaSharedHome import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript @@ -46,7 +45,7 @@ class JiraDataCenterPlanIT { val nodePlans = listOf(1, 2).map { val nodeHooks = PreInstallHooks.default() .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } - JiraNodePlan.Builder() + JiraNodePlan.Builder(infrastructure) .installation( ParallelInstallation( jiraHomeSource = jiraHomeSource, @@ -98,7 +97,7 @@ class JiraDataCenterPlanIT { } val nodePlans = listOf(1, 2).map { - JiraNodePlan.Builder() + JiraNodePlan.Builder(infrastructure) .installation( ParallelInstallation( jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome), diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 3c944099..4cd9c275 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -7,7 +7,6 @@ import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJir import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.io.api.resolveSafely @@ -38,7 +37,7 @@ class JiraServerPlanIT { // given val hooks = PreInstallHooks.default() .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } - val nodePlan = JiraNodePlan.Builder() + val nodePlan = JiraNodePlan.Builder(infrastructure) .hooks(hooks) .installation( ParallelInstallation( @@ -61,11 +60,7 @@ class JiraServerPlanIT { val jiraServer = try { jiraServerPlan.materialize() } catch (e: Exception) { - val debugging = Paths.get("build/test-artifacts/") - .resolveSafely(javaClass.simpleName) - .resolveSafely(Instant.now().toString()) - jiraServerPlan.report().downloadTo(debugging) - throw Exception("Jira Server plan failed to materialize, debugging info available in $debugging", e) + debug(jiraServerPlan, e) } val reports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) @@ -96,4 +91,20 @@ class JiraServerPlanIT { .`as`("GC logs from $fileTree") .isNotEmpty } + + private fun debug( + jiraServerPlan: JiraInstancePlan, + e: Exception + ) : Nothing { + val debugging = Paths.get("build/test-artifacts/") + .resolveSafely(javaClass.simpleName) + .resolveSafely(Instant.now().toString()) + try { + jiraServerPlan.report().downloadTo(debugging) + } catch (debuggingException: Exception) { + debuggingException.addSuppressed(e) + throw debuggingException + } + throw Exception("Jira Server plan failed to materialize, debugging info available in $debugging", e) + } } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt index 59dd1797..0a2fa4e7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/profiler/AsyncProfilerIT.kt @@ -5,8 +5,6 @@ import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJir import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNode -import com.atlassian.performance.tools.infrastructure.api.jira.node.JiraNodePlan import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK @@ -50,7 +48,7 @@ class AsyncProfilerIT { private fun testOnInstalledJira(ubuntuVersion: String, test: (InstalledJira) -> T) { DockerInfrastructure(ubuntuVersion).use { infra -> - val jiraNode = infra.serveTcp("jira") + val jiraNode = infra.serveHttp("jira") val installed = ParallelInstallation( jiraHomeSource = EmptyJiraHome(), productDistribution = PublicJiraSoftwareDistribution("7.13.0"), From 5c97388fb72f02fd444496e4d47475791bd2505f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 9 Jul 2021 13:20:24 +0200 Subject: [PATCH 44/73] Fix Tomcat config --- .../api/jira/install/ParallelInstallation.kt | 3 ++- .../jira/install/SequentialInstallation.kt | 5 +++- .../jira/install/TomcatConfig.kt | 26 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/TomcatConfig.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt index ec81eb86..a6d9b29c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/ParallelInstallation.kt @@ -7,6 +7,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jvm.JavaDevelopmentKit import com.atlassian.performance.tools.infrastructure.downloadRemotely import com.atlassian.performance.tools.infrastructure.installRemotely +import com.atlassian.performance.tools.infrastructure.jira.install.TomcatConfig import java.util.concurrent.Executors class ParallelInstallation( @@ -32,9 +33,9 @@ class ParallelInstallation( val java = pool.submitWithLogContext("java") { jdk.also { it.install(ssh) } } - TODO("${http.tcp.privateIp} is ignored and `InstalledJira.installation.resolve('server.xml')` still hardcodes ` Date: Fri, 23 Jul 2021 11:39:35 +0200 Subject: [PATCH 45/73] expose HttpNode --- .../tools/infrastructure/api/jira/install/HttpNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt index d4636e21..e7219f85 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install import java.net.URI -class HttpNode internal constructor( +class HttpNode( val tcp: TcpNode, private val basePath: String, private val supportsTls: Boolean From 68a9dfbec6a2f90d45ae66e4c2fa03285f32b1a8 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 23 Jul 2021 14:22:32 +0200 Subject: [PATCH 46/73] Split infra into server rooms --- .../infrastructure/api/Infrastructure.kt | 18 ------------- .../api/database/DockerMysqlServer.kt | 12 ++++----- .../api/jira/instance/JiraDataCenterPlan.kt | 25 ++++++++++++------- .../api/jira/instance/JiraNodePlan.kt | 19 ++++++++++---- .../api/jira/instance/JiraServerPlan.kt | 12 ++++++--- .../api/jira/sharedhome/NfsSharedHome.kt | 8 +++--- .../api/jira/sharedhome/SambaSharedHome.kt | 6 ++--- .../api/loadbalancer/ApacheProxyPlan.kt | 7 +++--- .../api/network/HttpServerRoom.kt | 8 ++++++ .../infrastructure/api/network/Networked.kt | 6 +++++ .../api/network/SshServerRoom.kt | 7 ++++++ .../api/network/TcpServerRoom.kt | 12 +++++++++ .../tools/infrastructure/Datasets.kt | 6 ++--- .../api/DockerInfrastructure.kt | 14 +++++++---- .../api/jira/instance/JiraDataCenterPlanIT.kt | 3 +-- .../api/jira/instance/JiraServerPlanIT.kt | 3 +-- .../tools/infrastructure/api/os/UbuntuIT.kt | 3 +-- 17 files changed, 103 insertions(+), 66 deletions(-) delete mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt deleted file mode 100644 index 82b1fdfe..00000000 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Infrastructure.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.atlassian.performance.tools.infrastructure.api - -import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode -import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.ssh.api.Ssh - -interface Infrastructure : AutoCloseable { // TODO rename to ServerRoom - - val subnet: String - - /** - * @return can be reached by the caller via [TcpNode.publicIp] and by the rest of the infra via [TcpNode.privateIp] - */ - fun serveTcp(name: String): TcpNode - fun serveHttp(name: String): HttpNode - fun serve(name: String, tcpPorts: List, udpPorts: List): TcpNode - fun serveSsh(name: String): Ssh -} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 4f1bc6dc..0b6f3c20 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -1,11 +1,11 @@ package com.atlassian.performance.tools.infrastructure.api.database -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.* import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.database.Mysql import com.atlassian.performance.tools.infrastructure.database.SshMysqlClient @@ -14,7 +14,7 @@ import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection class DockerMysqlServer private constructor( - private val infrastructure: Infrastructure, + private val serverRoom: TcpServerRoom, private val source: DatasetPackage, private val maxConnections: Int ) : PreInstanceHook { @@ -24,7 +24,7 @@ class DockerMysqlServer private constructor( hooks: PreInstanceHooks, reports: Reports ) { - val server = infrastructure.serveTcp("mysql") + val server = serverRoom.serveTcp("mysql") val client = server.ssh.newConnection().use { setup(it, server) } nodes.forEach { node -> node.postInstall.insert(DatabaseIpConfig(server.privateIp)) @@ -51,18 +51,18 @@ class DockerMysqlServer private constructor( } class Builder( - private var infrastructure: Infrastructure, + private var serverRoom: TcpServerRoom, private var source: DatasetPackage ) { private var maxConnections: Int = 151 - fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } + fun serverRoom(serverRoom: TcpServerRoom) = apply { this.serverRoom = serverRoom } fun source(source: DatasetPackage) = apply { this.source = source } fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } fun build(): DockerMysqlServer = DockerMysqlServer( - infrastructure, + serverRoom, source, maxConnections ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 0783d011..47710fa7 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -1,6 +1,5 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks @@ -9,8 +8,10 @@ import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancerPlan +import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom import java.net.URI import java.time.Duration +import java.util.function.Consumer import kotlin.streams.asStream import kotlin.streams.toList @@ -27,7 +28,7 @@ class JiraDataCenterPlan private constructor( instanceHooks.call(nodePlans.map { it.hooks }, reports) val http = nodePlans.mapIndexed { nodeIndex, plan -> val nodeNumber = nodeIndex + 1 - val http = plan.infrastructure.serveHttp("jira-node-$nodeNumber") + val http = plan.serverRoom.serveHttp("jira-node-$nodeNumber") PlannedHttpNode(http, plan) } val balancer = balancerPlan.materialize(http.map { it.http }, nodePlans.map { it.hooks.preStart }) @@ -75,15 +76,21 @@ class JiraDataCenterPlan private constructor( } class Builder( - infrastructure: Infrastructure + private var nodePlans: List, + private var balancerPlan: LoadBalancerPlan ) { - private var nodePlans: List = listOf(1, 2).map { - JiraNodePlan.Builder(infrastructure) - .hooks(PreInstallHooks.default().apply { postInstall.insert(DefaultClusterProperties()) }) - .build() - } private var instanceHooks: PreInstanceHooks = PreInstanceHooks.default() - private var balancerPlan: LoadBalancerPlan = ApacheProxyPlan(infrastructure) + + constructor( + serverRoom: HttpServerRoom + ) : this( + nodePlans = listOf(1, 2).map { + JiraNodePlan.Builder(serverRoom) + .dataCenter() + .build() + }, + balancerPlan = ApacheProxyPlan(serverRoom) + ) fun nodePlans(nodePlans: List) = apply { this.nodePlans = nodePlans } fun instanceHooks(instanceHooks: PreInstanceHooks) = apply { this.instanceHooks = instanceHooks } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt index 594e4696..922ddd28 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt @@ -1,6 +1,5 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation @@ -9,6 +8,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreI import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK +import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom import com.atlassian.performance.tools.infrastructure.jira.install.hook.HookedJiraInstallation import com.atlassian.performance.tools.infrastructure.jira.start.hook.HookedJiraStart import net.jcip.annotations.NotThreadSafe @@ -23,7 +23,7 @@ import net.jcip.annotations.NotThreadSafe * @since 4.19.0 */ class JiraNodePlan private constructor( - internal val infrastructure: Infrastructure, + internal val serverRoom: HttpServerRoom, internal val installation: JiraInstallation, internal val start: JiraStart, internal val hooks: PreInstallHooks @@ -31,7 +31,7 @@ class JiraNodePlan private constructor( @NotThreadSafe class Builder( - private var infrastructure: Infrastructure + private var serverRoom: HttpServerRoom ) { private var installation: JiraInstallation = ParallelInstallation( EmptyJiraHome(), @@ -41,13 +41,22 @@ class JiraNodePlan private constructor( private var start: JiraStart = JiraLaunchScript() private var hooks: PreInstallHooks = PreInstallHooks.default() - fun infrastructure(infrastructure: Infrastructure) = apply { this.infrastructure = infrastructure } + constructor(plan: JiraNodePlan) : this( + plan.serverRoom + ) { + this.installation = plan.installation + this.start = plan.start + this.hooks = plan.hooks + } + + fun serverRoom(serverRoom: HttpServerRoom) = apply { this.serverRoom = serverRoom } fun installation(installation: JiraInstallation) = apply { this.installation = installation } fun start(start: JiraStart) = apply { this.start = start } fun hooks(hooks: PreInstallHooks) = apply { this.hooks = hooks } + fun dataCenter() = hooks(PreInstallHooks.default().apply { postInstall.insert(DefaultClusterProperties()) }) fun build() = JiraNodePlan( - infrastructure, + serverRoom, HookedJiraInstallation(installation, hooks), HookedJiraStart(start, hooks.preStart), hooks diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 1f819e6d..284f160c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -1,8 +1,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira +import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom import java.net.URI class JiraServerPlan private constructor( @@ -15,7 +15,7 @@ class JiraServerPlan private constructor( override fun materialize(): JiraInstance { val nodeHooks = listOf(plan).map { it.hooks } hooks.call(nodeHooks, reports) - val http = plan.infrastructure.serveHttp("jira-node") + val http = plan.serverRoom.serveHttp("jira-node") val installed = plan.installation.install(http, reports) val started = plan.start.start(installed, reports) val instance = JiraServer(started) @@ -33,11 +33,15 @@ class JiraServerPlan private constructor( } class Builder( - infrastructure: Infrastructure + private var plan: JiraNodePlan + ) { - private var plan: JiraNodePlan = JiraNodePlan.Builder(infrastructure).build() private var hooks: PreInstanceHooks = PreInstanceHooks.default() + constructor(serverRoom: HttpServerRoom) : this( + plan = JiraNodePlan.Builder(serverRoom).build() + ) + fun plan(plan: JiraNodePlan) = apply { this.plan = plan } fun hooks(hooks: PreInstanceHooks) = apply { this.hooks = hooks } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt index cded91ed..67cb611d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt @@ -1,6 +1,5 @@ package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook @@ -9,6 +8,8 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreI import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.network.Networked +import com.atlassian.performance.tools.infrastructure.api.network.SshServerRoom import com.atlassian.performance.tools.infrastructure.api.os.RemotePath import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty @@ -16,7 +17,8 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class NfsSharedHome( private val jiraHomeSource: JiraHomeSource, - private val infrastructure: Infrastructure + private val infrastructure: SshServerRoom, + private val networked: Networked ) : PreInstanceHook { private val localHome = "/home/ubuntu/jira-shared-home" @@ -40,7 +42,7 @@ class NfsSharedHome( private fun export(ssh: SshConnection): SshConnection.SshResult { Ubuntu().install(ssh, listOf("nfs-kernel-server")) val options = "rw,sync,no_subtree_check,no_root_squash" - ssh.execute("sudo echo '$localHome ${infrastructure.subnet}($options)' | sudo tee -a /etc/exports") + ssh.execute("sudo echo '$localHome ${networked.subnetCidr}($options)' | sudo tee -a /etc/exports") return ssh.execute("sudo service nfs-kernel-server restart") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt index 7d364381..3d744054 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt @@ -1,6 +1,5 @@ package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode @@ -10,6 +9,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreI import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty import com.atlassian.performance.tools.ssh.api.SshConnection @@ -17,11 +17,11 @@ import java.util.* class SambaSharedHome( private val jiraHomeSource: JiraHomeSource, - private val infrastructure: Infrastructure + private val serverRoom: TcpServerRoom ) : PreInstanceHook { override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { - val server = infrastructure.serve("samba-shared-home", listOf(139, 445), listOf(137, 138)) + val server = serverRoom.serveTcp("samba-shared-home", listOf(139, 445), listOf(137, 138)) val mount = server.ssh.newConnection().use { ssh -> val sharedHome = download(ssh) export(ssh, sharedHome, server) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt index 5704ea7f..c3c498aa 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -1,13 +1,12 @@ package com.atlassian.performance.tools.infrastructure.api.loadbalancer -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.Sed import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction @@ -16,13 +15,13 @@ import java.net.URI import java.time.Duration class ApacheProxyPlan( - private val infrastructure: Infrastructure + private val serverRoom: HttpServerRoom ) : LoadBalancerPlan { private val configPath = "/etc/apache2/sites-enabled/000-default.conf" override fun materialize(nodes: List, hooks: List): LoadBalancer { - val proxyNode = infrastructure.serveHttp("apache-proxy") + val proxyNode = serverRoom.serveHttp("apache-proxy") IdempotentAction("Installing and configuring apache load balancer") { proxyNode.tcp.ssh.newConnection().use { connection -> tryToProvision(connection, nodes, proxyNode) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt new file mode 100644 index 00000000..c6701304 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt @@ -0,0 +1,8 @@ +package com.atlassian.performance.tools.infrastructure.api.network + +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode + +interface HttpServerRoom : AutoCloseable { + + fun serveHttp(name: String): HttpNode +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt new file mode 100644 index 00000000..bc85cc71 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt @@ -0,0 +1,6 @@ +package com.atlassian.performance.tools.infrastructure.api.network + +interface Networked { + + val subnetCidr: String +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt new file mode 100644 index 00000000..fcace766 --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt @@ -0,0 +1,7 @@ +package com.atlassian.performance.tools.infrastructure.api.network + +import com.atlassian.performance.tools.ssh.api.Ssh + +interface SshServerRoom : AutoCloseable { + fun serveSsh(name: String): Ssh +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt new file mode 100644 index 00000000..3ff31a6f --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt @@ -0,0 +1,12 @@ +package com.atlassian.performance.tools.infrastructure.api.network + +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode + +interface TcpServerRoom : AutoCloseable { + + /** + * @return reachable by the caller via [TcpNode.publicIp] and by the rest of the network via [TcpNode.privateIp] + */ + fun serveTcp(name: String): TcpNode + fun serveTcp(name: String, tcpPorts: List, udpPorts: List): TcpNode +} \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 0363e416..b4e78b39 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -1,12 +1,12 @@ package com.atlassian.performance.tools.infrastructure -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.RestUpgrade +import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import java.net.URI import java.time.Duration @@ -27,8 +27,8 @@ class Datasets { downloadTimeout = Duration.ofMinutes(6) ) - fun hookMysql(preInstanceHooks: PreInstanceHooks, infrastructure: Infrastructure) { - val mysqlServer = DockerMysqlServer.Builder(infrastructure, mysql).build() + fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { + val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() preInstanceHooks.insert(mysqlServer) } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index e21b1277..c7a3565f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -2,6 +2,10 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode +import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.api.network.Networked +import com.atlassian.performance.tools.infrastructure.api.network.SshServerRoom +import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.lib.docker.CreatedContainer import com.atlassian.performance.tools.infrastructure.lib.docker.DockerNetwork import com.atlassian.performance.tools.infrastructure.lib.docker.StartedContainer @@ -22,12 +26,12 @@ import java.util.concurrent.ConcurrentLinkedDeque internal class DockerInfrastructure( private val ubuntuVersion: String = "18.04" -) : Infrastructure { +) : SshServerRoom, TcpServerRoom, HttpServerRoom, Networked { private val allocatedResources: Deque = ConcurrentLinkedDeque() private val docker: DockerClient private val network: DockerNetwork - override val subnet: String + override val subnetCidr: String init { @@ -40,7 +44,7 @@ internal class DockerInfrastructure( .withName(randomUUID().toString()) .execAsResource(docker) allocatedResources.add(network) - subnet = docker + subnetCidr = docker .inspectNetworkCmd() .withNetworkId(network.response.id) .exec() @@ -75,11 +79,11 @@ internal class DockerInfrastructure( } private fun serveTcp(tcpPort: Int, name: String): TcpNode { - return serve(name, listOf(tcpPort), emptyList()) + return serveTcp(name, listOf(tcpPort), emptyList()) } - override fun serve(name: String, tcpPorts: List, udpPorts: List): TcpNode { + override fun serveTcp(name: String, tcpPorts: List, udpPorts: List): TcpNode { val ports = tcpPorts.map { ExposedPort.tcp(it) } + udpPorts.map { ExposedPort.udp(it) } + ExposedPort.tcp(22) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 8171c21b..104e61fa 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -2,7 +2,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.Datasets import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation @@ -26,7 +25,7 @@ import java.time.Duration.ofMinutes class JiraDataCenterPlanIT { - private lateinit var infrastructure: Infrastructure + private lateinit var infrastructure: DockerInfrastructure @Before fun setUp() { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 4cd9c275..84fb6c33 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -2,7 +2,6 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.Datasets import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation @@ -20,7 +19,7 @@ import java.time.Instant class JiraServerPlanIT { - private lateinit var infrastructure: Infrastructure + private lateinit var infrastructure: DockerInfrastructure @Before fun setUp() { diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt index a9f4e521..ed019fa2 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/os/UbuntuIT.kt @@ -1,7 +1,6 @@ package com.atlassian.performance.tools.infrastructure.api.os import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure -import com.atlassian.performance.tools.infrastructure.api.Infrastructure import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection import com.atlassian.performance.tools.ssh.api.SshHost @@ -14,7 +13,7 @@ import java.util.concurrent.* class UbuntuIT { private lateinit var executor: ExecutorService - private lateinit var infra: Infrastructure + private lateinit var infra: DockerInfrastructure private lateinit var ssh: Ssh @Before From 82ef621b29d26a843822aa75f5f4e118de2f3d8d Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 23 Jul 2021 14:38:07 +0200 Subject: [PATCH 47/73] Server rooms dont need to be closeable --- .../infrastructure/api/jira/sharedhome/NfsSharedHome.kt | 2 +- .../tools/infrastructure/api/network/HttpServerRoom.kt | 2 +- .../tools/infrastructure/api/network/Networked.kt | 5 ++++- .../tools/infrastructure/api/network/SshServerRoom.kt | 2 +- .../tools/infrastructure/api/network/TcpServerRoom.kt | 2 +- .../tools/infrastructure/api/DockerInfrastructure.kt | 6 ++++-- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt index 67cb611d..eaff9ec1 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt @@ -42,7 +42,7 @@ class NfsSharedHome( private fun export(ssh: SshConnection): SshConnection.SshResult { Ubuntu().install(ssh, listOf("nfs-kernel-server")) val options = "rw,sync,no_subtree_check,no_root_squash" - ssh.execute("sudo echo '$localHome ${networked.subnetCidr}($options)' | sudo tee -a /etc/exports") + ssh.execute("sudo echo '$localHome ${networked.subnet()}($options)' | sudo tee -a /etc/exports") return ssh.execute("sudo service nfs-kernel-server restart") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt index c6701304..89316ba6 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.network import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode -interface HttpServerRoom : AutoCloseable { +interface HttpServerRoom { fun serveHttp(name: String): HttpNode } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt index bc85cc71..27a9ee33 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/Networked.kt @@ -2,5 +2,8 @@ package com.atlassian.performance.tools.infrastructure.api.network interface Networked { - val subnetCidr: String + /** + * @return CIDR + */ + fun subnet(): String } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt index fcace766..90ae5632 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/SshServerRoom.kt @@ -2,6 +2,6 @@ package com.atlassian.performance.tools.infrastructure.api.network import com.atlassian.performance.tools.ssh.api.Ssh -interface SshServerRoom : AutoCloseable { +interface SshServerRoom { fun serveSsh(name: String): Ssh } \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt index 3ff31a6f..a8c786e6 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/TcpServerRoom.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.network import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -interface TcpServerRoom : AutoCloseable { +interface TcpServerRoom { /** * @return reachable by the caller via [TcpNode.publicIp] and by the rest of the network via [TcpNode.privateIp] diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index c7a3565f..e2254911 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -26,12 +26,12 @@ import java.util.concurrent.ConcurrentLinkedDeque internal class DockerInfrastructure( private val ubuntuVersion: String = "18.04" -) : SshServerRoom, TcpServerRoom, HttpServerRoom, Networked { +) : SshServerRoom, TcpServerRoom, HttpServerRoom, Networked, AutoCloseable { private val allocatedResources: Deque = ConcurrentLinkedDeque() private val docker: DockerClient private val network: DockerNetwork - override val subnetCidr: String + private val subnetCidr: String init { @@ -54,6 +54,8 @@ internal class DockerInfrastructure( .subnet } + override fun subnet(): String = subnetCidr + fun serveSsh(): Ssh = serveSsh("ssh") override fun serveSsh(name: String): Ssh { From 9d88f88b2a5334319f1d1444ef1d2279d8c57898 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 30 Jul 2021 15:41:00 +0200 Subject: [PATCH 48/73] Mount TCP shared home in private network --- .../api/jira/sharedhome/NfsSharedHome.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt index eaff9ec1..66c80bff 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt @@ -2,6 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks @@ -9,27 +10,25 @@ import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInsta import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.Networked -import com.atlassian.performance.tools.infrastructure.api.network.SshServerRoom -import com.atlassian.performance.tools.infrastructure.api.os.RemotePath +import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty import com.atlassian.performance.tools.ssh.api.SshConnection class NfsSharedHome( private val jiraHomeSource: JiraHomeSource, - private val infrastructure: SshServerRoom, + private val infrastructure: TcpServerRoom, private val networked: Networked ) : PreInstanceHook { private val localHome = "/home/ubuntu/jira-shared-home" override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { - val server = infrastructure.serveSsh("shared-home") - server.newConnection().use { ssh -> + val tcp = infrastructure.serveTcp("shared-home") + tcp.ssh.newConnection().use { ssh -> download(ssh) export(ssh) } - val sharedHome = RemotePath(server.host, localHome) - nodes.forEach { it.postInstall.insert(NfsMount(sharedHome)) } + nodes.forEach { it.postInstall.insert(NfsMount(tcp, localHome)) } } private fun download(ssh: SshConnection) { @@ -47,12 +46,13 @@ class NfsSharedHome( } private class NfsMount( - private val sharedHome: RemotePath + private val tcp: TcpNode, + private val sharedHome: String ) : PostInstallHook { override fun call(ssh: SshConnection, jira: InstalledJira, hooks: PostInstallHooks, reports: Reports) { Ubuntu().install(ssh, listOf("nfs-common")) - val mountSource = "${sharedHome.host.ipAddress}:${sharedHome.path}" + val mountSource = "${tcp.privateIp}:$sharedHome" val mountTarget = "mounted-shared-home" ssh.execute("mkdir -p $mountTarget") ssh.execute("sudo mount -o soft,intr,rsize=8192,wsize=8192 $mountSource $mountTarget") From 43b900a4dc0f5a395bada0a91f5b72c8487c9d83 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 30 Jul 2021 16:50:14 +0200 Subject: [PATCH 49/73] Call pre-instance hooks in parallel --- .../infrastructure/api/database/DockerMysqlServer.kt | 4 ++-- .../infrastructure/api/jira/instance/PreInstanceHook.kt | 2 +- .../infrastructure/api/jira/instance/PreInstanceHooks.kt | 9 +++------ .../infrastructure/api/jira/sharedhome/NfsSharedHome.kt | 4 ++-- .../api/jira/sharedhome/SambaSharedHome.kt | 3 ++- .../tools/infrastructure/api/DockerInfrastructure.kt | 1 - 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 0b6f3c20..0b9dab7f 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -21,7 +21,7 @@ class DockerMysqlServer private constructor( override fun call( nodes: List, - hooks: PreInstanceHooks, + hooks: PostInstanceHooks, reports: Reports ) { val server = serverRoom.serveTcp("mysql") @@ -30,7 +30,7 @@ class DockerMysqlServer private constructor( node.postInstall.insert(DatabaseIpConfig(server.privateIp)) node.postInstall.insert(MysqlConnector()) } - hooks.postInstance.insert(FixJiraUriViaMysql(client, server.ssh)) + hooks.insert(FixJiraUriViaMysql(client, server.ssh)) } private fun setup(ssh: SshConnection, server: TcpNode): SshSqlClient { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt index be674f40..10de8f1e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt @@ -12,7 +12,7 @@ interface PreInstanceHook { */ fun call( nodes: List, - hooks: PreInstanceHooks, + hooks: PostInstanceHooks, reports: Reports ) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt index 5643ca27..f732f6df 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt @@ -16,12 +16,9 @@ class PreInstanceHooks private constructor( } internal fun call(nodes: List, reports: Reports) { - while (true) { - hooks - .poll() - ?.call(nodes, this, reports) - ?: break - } + hooks + .parallelStream() + .forEach { it.call(nodes, postInstance, reports) } } companion object Factory { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt index 66c80bff..99f7072e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt @@ -6,8 +6,8 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.Networked import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom @@ -22,7 +22,7 @@ class NfsSharedHome( ) : PreInstanceHook { private val localHome = "/home/ubuntu/jira-shared-home" - override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { + override fun call(nodes: List, hooks: PostInstanceHooks, reports: Reports) { val tcp = infrastructure.serveTcp("shared-home") tcp.ssh.newConnection().use { ssh -> download(ssh) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt index 3d744054..da4d8c29 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt @@ -6,6 +6,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports @@ -20,7 +21,7 @@ class SambaSharedHome( private val serverRoom: TcpServerRoom ) : PreInstanceHook { - override fun call(nodes: List, hooks: PreInstanceHooks, reports: Reports) { + override fun call(nodes: List, hooks: PostInstanceHooks, reports: Reports) { val server = serverRoom.serveTcp("samba-shared-home", listOf(139, 445), listOf(137, 138)) val mount = server.ssh.newConnection().use { ssh -> val sharedHome = download(ssh) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index e2254911..4bce146a 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -33,7 +33,6 @@ internal class DockerInfrastructure( private val network: DockerNetwork private val subnetCidr: String - init { val dockerConfig = DefaultDockerClientConfig.createDefaultConfigBuilder().build() val dockerHttp = ZerodepDockerHttpClient.Builder().dockerHost(dockerConfig.dockerHost).build() From d95089643fc80dcb6899f852548cc569f6ef6902 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 6 Aug 2021 12:14:07 +0200 Subject: [PATCH 50/73] Stop trying to fix relative remote paths --- .../performance/tools/infrastructure/api/jira/report/Reports.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt index 4feca137..b9737f42 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/report/Reports.kt @@ -40,7 +40,6 @@ class Reports private constructor( // TODO turn into SPI to allow AWS CLI transp localDirectory.ensureDirectory() hostReports.groupBy { it.host }.map { (host, reports) -> host.ssh.newConnection().use { ssh -> - val remoteBase = RemotePath(ssh.getHost(), ssh.execute("pwd").output.trim()) reports .flatMap { report -> report.report.locate(ssh).map { path -> RemotePath(host.ssh.host, path) } @@ -48,7 +47,6 @@ class Reports private constructor( // TODO turn into SPI to allow AWS CLI transp .forEach { remotePath -> localDirectory .resolveSafely(host.name) - .resolve(remoteBase.toLocalRelativePath()) .resolve(remotePath.toLocalRelativePath()) .normalize() .let { remotePath.download(it) } From 127a5f222d9b44b84a4e4e448f053bcfe8886e86 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 3 Mar 2023 11:16:21 +0100 Subject: [PATCH 51/73] Report dbconfig.xml changes --- .../tools/infrastructure/api/database/DatabaseIpConfig.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt index da00606b..950e73a4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt @@ -5,6 +5,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.Installed import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection class DatabaseIpConfig( @@ -17,11 +18,13 @@ class DatabaseIpConfig( hooks: PostInstallHooks, reports: Reports ) { + val dbConfigXml = jira.home.resolve("dbconfig.xml").path + reports.add(StaticReport(dbConfigXml), jira) Sed().replace( connection = ssh, expression = "(.*(@(//)?|//))" + "([^:/]+)" + "(.*)", output = """\1$databaseIp\5""", - file = "${jira.home.path}/dbconfig.xml" + file = dbConfigXml ) } } \ No newline at end of file From 9efee923865f0d93698c2e93e00a33fb213876fa Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 3 Mar 2023 15:56:34 +0100 Subject: [PATCH 52/73] JPERF-273: Hook in MySQL-Jira connection Follow the sample from the docs instead of relying on an ancient dbconfig.xml from `JiraHomeSource`. Hide those components from API. Maybe when we add support for more than MySQL 5.7, we will see common patterns to expose for reuse. For now, customizers will just have to write their own hooks. --- .../api/database/DockerMysqlServer.kt | 13 +++--- .../tools/infrastructure/api/os/RemotePath.kt | 9 ++++ .../MysqlFiveConnector.kt} | 18 ++++---- .../database/MysqlFiveDotSevenJiraConfig.kt | 45 +++++++++++++++++++ 4 files changed, 70 insertions(+), 15 deletions(-) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api/database/MysqlConnector.kt => database/MysqlFiveConnector.kt} (68%) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 0b9dab7f..069b9a91 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -3,13 +3,14 @@ package com.atlassian.performance.tools.infrastructure.api.database import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.* +import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraInstance +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHook +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks +import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu -import com.atlassian.performance.tools.infrastructure.database.Mysql -import com.atlassian.performance.tools.infrastructure.database.SshMysqlClient -import com.atlassian.performance.tools.infrastructure.database.SshSqlClient +import com.atlassian.performance.tools.infrastructure.database.* import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection @@ -27,8 +28,8 @@ class DockerMysqlServer private constructor( val server = serverRoom.serveTcp("mysql") val client = server.ssh.newConnection().use { setup(it, server) } nodes.forEach { node -> - node.postInstall.insert(DatabaseIpConfig(server.privateIp)) - node.postInstall.insert(MysqlConnector()) + node.postInstall.insert(MysqlFiveDotSevenJiraConfig(server)) + node.postInstall.insert(MysqlFiveConnector()) } hooks.insert(FixJiraUriViaMysql(client, server.ssh)) } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/os/RemotePath.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/os/RemotePath.kt index e61537bb..7c77e952 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/os/RemotePath.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/os/RemotePath.kt @@ -54,6 +54,15 @@ class RemotePath( return localDestination.toFile() } + fun upload( + localSource: File + ): RemotePath { + Ssh(host, connectivityPatience = 4).newConnection().use { ssh -> + ssh.upload(localSource, path) + } + return this + } + override fun toString(): String { return "RemotePath(host=$host, path='$path')" } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt similarity index 68% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt index b4a13348..487a4c9c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/MysqlConnector.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.database +package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook @@ -8,8 +8,12 @@ import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection import java.time.Duration +import java.time.Duration.ofSeconds -class MysqlConnector : PostInstallHook { +/** + * [docs](https://confluence.atlassian.com/adminjiraserver/connecting-jira-applications-to-mysql-5-7-966063305.html#ConnectingJiraapplicationstoMySQL5.7-driver) + */ +class MysqlFiveConnector : PostInstallHook { override fun call( ssh: SshConnection, @@ -18,13 +22,9 @@ class MysqlConnector : PostInstallHook { reports: Reports ) { val connector = "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz" - IdempotentAction( - description = "Download MySQL connector", - action = { ssh.execute("wget -q $connector") } - ).retry( - maxAttempts = 3, - backoff = StaticBackoff(Duration.ofSeconds(5)) - ) + IdempotentAction("Download MySQL connector") { + ssh.execute("wget -q $connector") + }.retry(3, StaticBackoff(ofSeconds(5))) ssh.execute("tar -xzf mysql-connector-java-5.1.40.tar.gz") ssh.execute("cp mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${jira.installation.path}/lib") } diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt new file mode 100644 index 00000000..8f0f2d7a --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt @@ -0,0 +1,45 @@ +package com.atlassian.performance.tools.infrastructure.database + +import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira +import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport +import com.atlassian.performance.tools.infrastructure.api.os.RemotePath +import com.atlassian.performance.tools.ssh.api.SshConnection +import java.io.File +import java.nio.file.Files + +/** + * [docs](https://confluence.atlassian.com/adminjiraserver/connecting-jira-applications-to-mysql-5-7-966063305.html#ConnectingJiraapplicationstoMySQL5.7-dbconnectionfields) + */ +class MysqlFiveDotSevenJiraConfig( + private val mysql: TcpNode +) : PostInstallHook { + + override fun call( + ssh: SshConnection, + jira: InstalledJira, + hooks: PostInstallHooks, + reports: Reports + ) { + val remoteConfig: RemotePath = jira.home.resolve("dbconfig.xml") + reports.add(StaticReport(remoteConfig.path), jira) + val config: String = renderConfig() + val localConfig: File = Files.createTempFile("dbconfig", ".xml") + .toFile() + .also { it.writeText(config) } + remoteConfig.upload(localConfig) + } + + private fun renderConfig(): String { + val configTemplate = javaClass.classLoader.getResourceAsStream("mysql-dbconfig.xml").use { + it!!.bufferedReader().readText() + } + return configTemplate + .replace("dbserver", mysql.privateIp) + .replace(":3306", ":${mysql.port}") + + } +} From aab3f46d8451d44e2f202bd27b357b0a5bc98491 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 22 Mar 2023 14:56:34 +0100 Subject: [PATCH 53/73] JPERF-273: Parametrize MySQL version --- .../tools/infrastructure/api/database/DockerMysqlServer.kt | 5 +++++ .../performance/tools/infrastructure/database/MySql.kt | 5 +++-- .../atlassian/performance/tools/infrastructure/Datasets.kt | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 069b9a91..6a781065 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -16,6 +16,7 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class DockerMysqlServer private constructor( private val serverRoom: TcpServerRoom, + private var mysqlVersion: String, private val source: DatasetPackage, private val maxConnections: Int ) : PreInstanceHook { @@ -38,6 +39,7 @@ class DockerMysqlServer private constructor( val mysqlDataLocation = source.download(ssh) val containerName = Mysql.container( dataDir = mysqlDataLocation, + mysqlVersion = mysqlVersion, extraParameters = emptyArray(), extraArguments = arrayOf( "--skip-grant-tables", // Recovery mode, as some datasets give no permissions to their root DB user @@ -56,14 +58,17 @@ class DockerMysqlServer private constructor( private var source: DatasetPackage ) { + private var mysqlVersion: String = "5.7.32" private var maxConnections: Int = 151 fun serverRoom(serverRoom: TcpServerRoom) = apply { this.serverRoom = serverRoom } + fun mysqlVersion(mysqlVersion: String) = apply { this.mysqlVersion = mysqlVersion } fun source(source: DatasetPackage) = apply { this.source = source } fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } fun build(): DockerMysqlServer = DockerMysqlServer( serverRoom, + mysqlVersion, source, maxConnections ) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index 1fe0707d..bb3e881c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -40,9 +40,10 @@ internal object Mysql { dataDir: String, extraParameters: Array, extraArguments: Array, - host: TcpNode? = null + host: TcpNode? = null, + mysqlVersion: String = "5.7.32" ) = DockerContainer.Builder() - .imageName("mysql:5.7.32") + .imageName("mysql:$mysqlVersion") .pullTimeout(Duration.ofMinutes(5)) .parameters( host?.port?.let { "-p $it:$it" } ?: "-p 3306:3306", diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index b4e78b39..a04f7572 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -28,7 +28,9 @@ class Datasets { ) fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { - val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() + val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql) + .mysqlVersion("5.6.42") + .build() preInstanceHooks.insert(mysqlServer) } From f305eafcd48637e83a0e4bd362d81c1b529ab06b Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 27 Mar 2023 14:48:25 +0200 Subject: [PATCH 54/73] JPERF-273: Try `SmallJiraEightDataset` --- .../tools/infrastructure/Datasets.kt | 29 +++++++++++++++++++ .../api/jira/instance/JiraServerPlanIT.kt | 8 ++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index a04f7572..8f03cf29 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -42,4 +42,33 @@ class Datasets { postStartHooks.insert(dataUpgrade) } } + + object SmallJiraEightDataset { + private val s3Bucket = URI("https://s3-eu-central-1.amazonaws.com/") + .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1nrja8d1upind/") + .resolve("dataset-a533e558-e5c5-46e7-9398-5aeda84d793a/") + + private val mysql = HttpDatasetPackage( + uri = s3Bucket.resolve("database.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) + + val jiraHome = HttpDatasetPackage( + uri = s3Bucket.resolve("jirahome.tar.bz2"), + downloadTimeout = Duration.ofMinutes(6) + ) + + fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { + val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() + preInstanceHooks.insert(mysqlServer) + } + + fun hookDataUpgrade(postStartHooks: PostStartHooks) { + val timeouts = JiraLaunchTimeouts.Builder() + .initTimeout(Duration.ofMinutes(4)) + .build() + val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") + postStartHooks.insert(dataUpgrade) + } + } } \ No newline at end of file diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 84fb6c33..50a0c23f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -35,13 +35,13 @@ class JiraServerPlanIT { fun shouldStartJiraWithHooks() { // given val hooks = PreInstallHooks.default() - .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } + .also { Datasets.SmallJiraEightDataset.hookDataUpgrade(it.postStart) } val nodePlan = JiraNodePlan.Builder(infrastructure) .hooks(hooks) .installation( ParallelInstallation( - jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome), - productDistribution = PublicJiraSoftwareDistribution("7.13.0"), + jiraHomeSource = JiraHomePackage(Datasets.SmallJiraEightDataset.jiraHome), + productDistribution = PublicJiraSoftwareDistribution("9.0.0"), jdk = AdoptOpenJDK() ) ) @@ -49,7 +49,7 @@ class JiraServerPlanIT { .hooks(hooks) .build() val instanceHooks = PreInstanceHooks.default() - .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } + .also { Datasets.SmallJiraEightDataset.hookMysql(it, infrastructure) } val jiraServerPlan = JiraServerPlan.Builder(infrastructure) .plan(nodePlan) .hooks(instanceHooks) From 19f93f31733e8a1445c9916bdb6b84942653c62c Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 6 Sep 2023 13:56:36 +0200 Subject: [PATCH 55/73] JPERF-273: Poll MySQL twice a second --- .../performance/tools/infrastructure/database/MySql.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt index bb3e881c..e5467310 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MySql.kt @@ -31,6 +31,9 @@ internal object Mysql { "--innodb-log-file-size=2G" ) + private val pollPeriod = Duration.ofMillis(500) + private val maxWait = Duration.ofMinutes(15) + fun installClient(ssh: SshConnection): SshSqlClient { ubuntu.install(ssh, listOf("mysql-client")) return SshMysqlClient() @@ -57,17 +60,18 @@ internal object Mysql { .build() fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient) { - val backoff = StaticBackoff(ofSeconds(10)) + val backoff = StaticBackoff(pollPeriod) awaitDatabase(ssh, sqlClient, backoff) } fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient, containerName: String) { - val backoff = DeadContainerCheck(containerName, ssh, StaticBackoff(ofSeconds(10))) + val backoff = DeadContainerCheck(containerName, ssh, StaticBackoff(pollPeriod)) awaitDatabase(ssh, sqlClient, backoff) } private fun awaitDatabase(ssh: SshConnection, sqlClient: SshSqlClient, backoff: Backoff) { + val maxAttempts = maxWait.toMillis() / pollPeriod.toMillis() IdempotentAction("wait for MySQL start") { sqlClient.runSql(ssh, "select 1;") } - .retry(90, backoff) + .retry(maxAttempts.toInt(), backoff) } } \ No newline at end of file From 57eae456583a1521a8add0c423f52c9f91357744 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 6 Sep 2023 13:57:00 +0200 Subject: [PATCH 56/73] JPERF-273: Add .jenv --- .java-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .java-version diff --git a/.java-version b/.java-version new file mode 100644 index 00000000..62593409 --- /dev/null +++ b/.java-version @@ -0,0 +1 @@ +1.8 From 10f633ca84ffad887d8f548a22a41007ff090c4d Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 6 Sep 2023 13:57:18 +0200 Subject: [PATCH 57/73] JPERF-273: Align MySQL version to 5.7.32 TODO: why do we have to specify it in multiple places? --- .../com/atlassian/performance/tools/infrastructure/Datasets.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 8f03cf29..e89a12d5 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -29,7 +29,7 @@ class Datasets { fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql) - .mysqlVersion("5.6.42") + .mysqlVersion("5.7.32") .build() preInstanceHooks.insert(mysqlServer) } From 9d1a328677a667b2eb130e2ff9d246cb19bf2f9f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 6 Sep 2023 13:57:46 +0200 Subject: [PATCH 58/73] JPERF-273: Fix expected log paths --- .../api/jira/instance/JiraDataCenterPlanIT.kt | 6 +++--- .../infrastructure/api/jira/instance/JiraServerPlanIT.kt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 104e61fa..1f34564f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -126,9 +126,9 @@ class JiraDataCenterPlanIT { .map { reports.toPath().relativize(it.toPath()) } .toList() assertThat(fileTree.map { it.toString() }).contains( - "jira-node-1/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", - "jira-node-1/root/~/jpt-jstat.log", - "jira-node-2/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out" + "jira-node-1/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", + "jira-node-1/~/jpt-jstat.log", + "jira-node-2/atlassian-jira-software-7.13.0-standalone/logs/catalina.out" ) assertThat(fileTree.filter { it.fileName.toString() == "atlassian-jira.log" }) .`as`("Jira log from $fileTree") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index 50a0c23f..f2be721a 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -78,10 +78,10 @@ class JiraServerPlanIT { .map { reports.toPath().relativize(it.toPath()) } .toList() assertThat(fileTree.map { it.toString() }).contains( - "jira-node/root/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", - "jira-node/root/~/jpt-jstat.log", - "jira-node/root/~/jpt-vmstat.log", - "jira-node/root/~/jpt-iostat.log" + "jira-node/atlassian-jira-software-$jiraServer-standalone/logs/catalina.out", + "jira-node/~/jpt-jstat.log", + "jira-node/~/jpt-vmstat.log", + "jira-node/~/jpt-iostat.log" ) assertThat(fileTree.filter { it.fileName.toString().startsWith("access_log") }) .`as`("access logs from $fileTree") From aa9cfe11a410b1fff79a00c7ae3093650fa9ea8c Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 Aug 2020 10:14:42 +0200 Subject: [PATCH 59/73] JPERF-273 Fix JiraDataCenterPlanIT --- .../tools/infrastructure/Datasets.kt | 36 ++++--------------- .../api/jira/instance/JiraDataCenterPlanIT.kt | 19 +++++----- .../api/jira/instance/JiraServerPlanIT.kt | 11 +++--- 3 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index e89a12d5..f4e45eb1 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -11,11 +11,10 @@ import java.net.URI import java.time.Duration class Datasets { - - object JiraSevenDataset { - private val s3Bucket = URI("https://s3-eu-west-1.amazonaws.com/") - .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1sjxdtrv5hdhj/") - .resolve("dataset-f8dba866-9d1b-492e-b76c-f4a78ac3958c/") + object SmallJiraEightDataset { + private val s3Bucket = URI("https://s3-eu-central-1.amazonaws.com/") + .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1nrja8d1upind/") + .resolve("dataset-a533e558-e5c5-46e7-9398-5aeda84d793a/") private val mysql = HttpDatasetPackage( uri = s3Bucket.resolve("database.tar.bz2"), @@ -28,9 +27,7 @@ class Datasets { ) fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { - val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql) - .mysqlVersion("5.7.32") - .build() + val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() preInstanceHooks.insert(mysqlServer) } @@ -41,27 +38,6 @@ class Datasets { val dataUpgrade = RestUpgrade(timeouts, "admin", "admin") postStartHooks.insert(dataUpgrade) } - } - - object SmallJiraEightDataset { - private val s3Bucket = URI("https://s3-eu-central-1.amazonaws.com/") - .resolve("jpt-custom-datasets-storage-a008820-datasetbucket-1nrja8d1upind/") - .resolve("dataset-a533e558-e5c5-46e7-9398-5aeda84d793a/") - - private val mysql = HttpDatasetPackage( - uri = s3Bucket.resolve("database.tar.bz2"), - downloadTimeout = Duration.ofMinutes(6) - ) - - val jiraHome = HttpDatasetPackage( - uri = s3Bucket.resolve("jirahome.tar.bz2"), - downloadTimeout = Duration.ofMinutes(6) - ) - - fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { - val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() - preInstanceHooks.insert(mysqlServer) - } fun hookDataUpgrade(postStartHooks: PostStartHooks) { val timeouts = JiraLaunchTimeouts.Builder() @@ -71,4 +47,4 @@ class Datasets { postStartHooks.insert(dataUpgrade) } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index 1f34564f..f8666e24 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -26,6 +26,9 @@ import java.time.Duration.ofMinutes class JiraDataCenterPlanIT { private lateinit var infrastructure: DockerInfrastructure + private val dataset = Datasets.SmallJiraEightDataset + private val jiraVersion = "9.4.9" + private val jiraDistribution = PublicJiraSoftwareDistribution(jiraVersion) @Before fun setUp() { @@ -40,15 +43,15 @@ class JiraDataCenterPlanIT { @Test fun shouldStartDataCenter() { // given - val jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome) + val jiraHomeSource = JiraHomePackage(dataset.jiraHome) val nodePlans = listOf(1, 2).map { val nodeHooks = PreInstallHooks.default() - .also { Datasets.JiraSevenDataset.hookMysql(it.postStart) } + .also { dataset.hookMysql(it.postStart) } JiraNodePlan.Builder(infrastructure) .installation( ParallelInstallation( jiraHomeSource = jiraHomeSource, - productDistribution = PublicJiraSoftwareDistribution("7.13.0"), + productDistribution = jiraDistribution, jdk = AdoptOpenJDK() ) ) @@ -57,7 +60,7 @@ class JiraDataCenterPlanIT { .build() } val instanceHooks = PreInstanceHooks.default() - .also { Datasets.JiraSevenDataset.hookMysql(it, infrastructure) } + .also { dataset.hookMysql(it, infrastructure) } .also { it.insert(SambaSharedHome(jiraHomeSource, infrastructure)) } val dcPlan = JiraDataCenterPlan.Builder(infrastructure) .nodePlans(nodePlans) @@ -99,8 +102,8 @@ class JiraDataCenterPlanIT { JiraNodePlan.Builder(infrastructure) .installation( ParallelInstallation( - jiraHomeSource = JiraHomePackage(Datasets.JiraSevenDataset.jiraHome), - productDistribution = PublicJiraSoftwareDistribution("7.13.0"), + jiraHomeSource = JiraHomePackage(dataset.jiraHome), + productDistribution = jiraDistribution, jdk = AdoptOpenJDK() ) ) @@ -126,9 +129,9 @@ class JiraDataCenterPlanIT { .map { reports.toPath().relativize(it.toPath()) } .toList() assertThat(fileTree.map { it.toString() }).contains( - "jira-node-1/atlassian-jira-software-7.13.0-standalone/logs/catalina.out", + "jira-node-1/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out", "jira-node-1/~/jpt-jstat.log", - "jira-node-2/atlassian-jira-software-7.13.0-standalone/logs/catalina.out" + "jira-node-2/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out" ) assertThat(fileTree.filter { it.fileName.toString() == "atlassian-jira.log" }) .`as`("Jira log from $fileTree") diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt index f2be721a..cc57ec61 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt @@ -20,6 +20,9 @@ import java.time.Instant class JiraServerPlanIT { private lateinit var infrastructure: DockerInfrastructure + private val dataset = Datasets.SmallJiraEightDataset + private val jiraVersion = "9.4.9" + private val jiraDistribution = PublicJiraSoftwareDistribution(jiraVersion) @Before fun setUp() { @@ -35,13 +38,13 @@ class JiraServerPlanIT { fun shouldStartJiraWithHooks() { // given val hooks = PreInstallHooks.default() - .also { Datasets.SmallJiraEightDataset.hookDataUpgrade(it.postStart) } + .also { dataset.hookDataUpgrade(it.postStart) } val nodePlan = JiraNodePlan.Builder(infrastructure) .hooks(hooks) .installation( ParallelInstallation( - jiraHomeSource = JiraHomePackage(Datasets.SmallJiraEightDataset.jiraHome), - productDistribution = PublicJiraSoftwareDistribution("9.0.0"), + jiraHomeSource = JiraHomePackage(dataset.jiraHome), + productDistribution = jiraDistribution, jdk = AdoptOpenJDK() ) ) @@ -49,7 +52,7 @@ class JiraServerPlanIT { .hooks(hooks) .build() val instanceHooks = PreInstanceHooks.default() - .also { Datasets.SmallJiraEightDataset.hookMysql(it, infrastructure) } + .also { dataset.hookMysql(it, infrastructure) } val jiraServerPlan = JiraServerPlan.Builder(infrastructure) .plan(nodePlan) .hooks(instanceHooks) From 087f50586c3f7006ae34385d6405e93f5d526cb4 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Wed, 6 Sep 2023 15:49:01 +0200 Subject: [PATCH 60/73] JPERF-273: Hardcode encrypted test admin password --- .../api/database/DockerMysqlServer.kt | 13 ++++++++++--- .../performance/tools/infrastructure/Datasets.kt | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index 6a781065..fe791fed 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -16,9 +16,10 @@ import com.atlassian.performance.tools.ssh.api.SshConnection class DockerMysqlServer private constructor( private val serverRoom: TcpServerRoom, - private var mysqlVersion: String, + private val mysqlVersion: String, private val source: DatasetPackage, - private val maxConnections: Int + private val maxConnections: Int, + private val extraSqls: List ) : PreInstanceHook { override fun call( @@ -50,6 +51,7 @@ class DockerMysqlServer private constructor( Ubuntu().install(ssh, listOf("mysql-client")) val client = SshMysqlClient("127.0.0.1", server.port) Mysql.awaitDatabase(ssh, client, containerName) + extraSqls.forEach { client.runSql(ssh, it) } return client } @@ -60,17 +62,22 @@ class DockerMysqlServer private constructor( private var mysqlVersion: String = "5.7.32" private var maxConnections: Int = 151 + private var extraSqls: MutableList = mutableListOf() fun serverRoom(serverRoom: TcpServerRoom) = apply { this.serverRoom = serverRoom } fun mysqlVersion(mysqlVersion: String) = apply { this.mysqlVersion = mysqlVersion } fun source(source: DatasetPackage) = apply { this.source = source } fun maxConnections(maxConnections: Int) = apply { this.maxConnections = maxConnections } + fun setPassword(user: String, password: String) = apply { + extraSqls.add("UPDATE jiradb.cwd_user SET credential='$password' WHERE user_name='$user';") + } fun build(): DockerMysqlServer = DockerMysqlServer( serverRoom, mysqlVersion, source, - maxConnections + maxConnections, + ArrayList(extraSqls) ) } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index f4e45eb1..e5d4dae4 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -27,7 +27,11 @@ class Datasets { ) fun hookMysql(preInstanceHooks: PreInstanceHooks, serverRoom: TcpServerRoom) { - val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql).build() + // encrypted with atlassian-password-encoder + val encryptedAdmin = "{PKCS5S2}dHH7Ws1DcJ1H4d9C8BN1Kh83ciEXVy025l9mIM8P3mlseybpKtI83531tOIyE/gb" + val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql) + .setPassword("admin", encryptedAdmin) + .build() preInstanceHooks.insert(mysqlServer) } From 4965f97008419df23ab321929ea6be75a053a2c0 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Thu, 7 Sep 2023 09:50:09 +0200 Subject: [PATCH 61/73] JPERF-273: Install JDK fonts Avoid errors in Jira logs like: ``` Caused by: java.lang.NullPointerException at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) [?:1.8.0-adoptopenjdk] at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) [?:1.8.0-adoptopenjdk] at sun.awt.FontConfiguration.init(FontConfiguration.java:107) [?:1.8.0-adoptopenjdk] at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) [?:1.8.0-adoptopenjdk] at sun.font.SunFontManager$2.run(SunFontManager.java:431) [?:1.8.0-adoptopenjdk] at java.security.AccessController.doPrivileged(Native Method) [?:1.8.0-adoptopenjdk] at sun.font.SunFontManager.(SunFontManager.java:376) [?:1.8.0-adoptopenjdk] at sun.awt.FcFontManager.(FcFontManager.java:35) [?:1.8.0-adoptopenjdk] at sun.awt.X11FontManager.(X11FontManager.java:57) [?:1.8.0-adoptopenjdk] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [?:1.8.0-adoptopenjdk] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) [?:1.8.0-adoptopenjdk] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) [?:1.8.0-adoptopenjdk] at java.lang.reflect.Constructor.newInstance(Constructor.java:423) [?:1.8.0-adoptopenjdk] at java.lang.Class.newInstance(Class.java:442) [?:1.8.0-adoptopenjdk] at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) [?:1.8.0-adoptopenjdk] at java.security.AccessController.doPrivileged(Native Method) [?:1.8.0-adoptopenjdk] at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) [?:1.8.0-adoptopenjdk] at java.awt.Font.getFont2D(Font.java:491) [?:1.8.0-adoptopenjdk] at java.awt.Font.canDisplay(Font.java:1980) [?:1.8.0-adoptopenjdk] at com.octo.captcha.component.image.fontgenerator.RandomFontGenerator.checkFontCanDisplayCharacters(RandomFontGenerator.java:223) [jcaptcha-2.0-alpha-1.jar:?] at com.octo.captcha.component.image.fontgenerator.RandomFontGenerator.cleanFontList(RandomFontGenerator.java:179) [jcaptcha-2.0-alpha-1.jar:?] at com.octo.captcha.component.image.fontgenerator.RandomFontGenerator.initializeFonts(RandomFontGenerator.java:94) [jcaptcha-2.0-alpha-1.jar:?] at com.octo.captcha.component.image.fontgenerator.RandomFontGenerator.(RandomFontGenerator.java:81) [jcaptcha-2.0-alpha-1.jar:?] at com.atlassian.jira.servlet.CensoredCaptchaEngine.createFontGenerator(CensoredCaptchaEngine.java:86) [classes/:?] at com.atlassian.jira.servlet.CensoredCaptchaEngine.createWord2Image(CensoredCaptchaEngine.java:65) [classes/:?] at com.atlassian.jira.servlet.CensoredCaptchaEngine.buildInitialFactories(CensoredCaptchaEngine.java:48) [classes/:?] at com.octo.captcha.engine.image.ListImageCaptchaEngine.(ListImageCaptchaEngine.java:24) [jcaptcha-2.0-alpha-1.jar:?] at com.atlassian.jira.servlet.CensoredCaptchaEngine.(CensoredCaptchaEngine.java:39) [classes/:?] at com.atlassian.jira.servlet.JiraImageCaptchaServiceImpl.(JiraImageCaptchaServiceImpl.java:13) [classes/:?] ... 137 more ``` --- .../tools/infrastructure/api/jvm/AdoptOpenJDK.kt | 1 + .../infrastructure/api/jvm/AdoptOpenJDK11.kt | 1 + .../tools/infrastructure/api/jvm/JdkFonts.kt | 15 +++++++++++++++ .../tools/infrastructure/api/jvm/OracleJDK.kt | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt index 823fe87d..9bd394fe 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK.kt @@ -23,6 +23,7 @@ class AdoptOpenJDK : VersionedJavaDevelopmentKit { download(connection) connection.execute("tar -xzf $jdkArchive") connection.execute("echo '${use()}' >> ~/.profile") + JdkFonts().install(connection) } override fun use(): String { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt index 0d567200..34030eed 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/AdoptOpenJDK11.kt @@ -29,6 +29,7 @@ class AdoptOpenJDK11 : VersionedJavaDevelopmentKit { download(connection) connection.execute("tar -xzf $jdkArchive") connection.execute("echo '${use()}' >> ~/.profile") + JdkFonts().install(connection) } override fun use(): String = diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt new file mode 100644 index 00000000..ebb182fe --- /dev/null +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt @@ -0,0 +1,15 @@ +package com.atlassian.performance.tools.infrastructure.api.jvm + +import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.ssh.api.SshConnection + +class JdkFonts { + + fun install(ssh: SshConnection) { + val packages = listOf( + "fonts-dejavu-core", // https://confluence.atlassian.com/bitbucketserverkb/captcha-image-doesn-t-render-779171210.html + "fontconfig" // https://jira.atlassian.com/browse/CONFSRVDEV-8954 + ) + Ubuntu().install(ssh, packages) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt index 2800c926..ce499402 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/OracleJDK.kt @@ -7,7 +7,6 @@ import org.apache.logging.log4j.Logger import java.net.URI import java.time.Duration - class OracleJDK : VersionedJavaDevelopmentKit { private val logger: Logger = LogManager.getLogger(this::class.java) private val jdkUpdate = 131 @@ -30,6 +29,7 @@ class OracleJDK : VersionedJavaDevelopmentKit { download(connection) connection.execute("tar -xzf $jdkArchive") connection.execute("echo '${use()}' >> ~/.profile") + JdkFonts().install(connection) } override fun use(): String = "export PATH=$jreBin:$bin:${'$'}PATH; export JAVA_HOME=$path" From 4c55f6dfc3fae336800e388bcea869ac5ece6e0f Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Fri, 7 Aug 2020 10:14:42 +0200 Subject: [PATCH 62/73] JPERF-273 Reset captcha --- .../infrastructure/api/database/DockerMysqlServer.kt | 12 ++++++++++++ .../tools/infrastructure/api/jvm/JdkFonts.kt | 2 +- .../performance/tools/infrastructure/Datasets.kt | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index fe791fed..c84f4967 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -72,6 +72,18 @@ class DockerMysqlServer private constructor( extraSqls.add("UPDATE jiradb.cwd_user SET credential='$password' WHERE user_name='$user';") } + fun resetCaptcha(user: String) = apply { + resetAttribute(user, "login.totalFailedCount") + resetAttribute(user, "login.currentFailedCount") + } + + private fun resetAttribute(user: String, attribute: String) { + val sql = "UPDATE jiradb.cwd_user_attributes SET attribute_value = '0'" + + "WHERE user_id = (SELECT id FROM jiradb.cwd_user WHERE user_name = '$user')" + + "AND attribute_name = '$attribute';" + extraSqls.add(sql) + } + fun build(): DockerMysqlServer = DockerMysqlServer( serverRoom, mysqlVersion, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt index ebb182fe..65d033c8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt @@ -12,4 +12,4 @@ class JdkFonts { ) Ubuntu().install(ssh, packages) } -} \ No newline at end of file +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index e5d4dae4..6658dac5 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -31,6 +31,7 @@ class Datasets { val encryptedAdmin = "{PKCS5S2}dHH7Ws1DcJ1H4d9C8BN1Kh83ciEXVy025l9mIM8P3mlseybpKtI83531tOIyE/gb" val mysqlServer = DockerMysqlServer.Builder(serverRoom, mysql) .setPassword("admin", encryptedAdmin) + .resetCaptcha("admin") .build() preInstanceHooks.insert(mysqlServer) } From 0291ca9c18ec3e127ef78bb17a5c574d69988004 Mon Sep 17 00:00:00 2001 From: Mikolaj Grzaslewicz Date: Thu, 7 Sep 2023 10:55:18 +0200 Subject: [PATCH 63/73] JPERF-273 Install only required packages to make jira captcha work --- .../performance/tools/infrastructure/api/jvm/JdkFonts.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt index 65d033c8..81e3786a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jvm/JdkFonts.kt @@ -7,7 +7,6 @@ class JdkFonts { fun install(ssh: SshConnection) { val packages = listOf( - "fonts-dejavu-core", // https://confluence.atlassian.com/bitbucketserverkb/captcha-image-doesn-t-render-779171210.html "fontconfig" // https://jira.atlassian.com/browse/CONFSRVDEV-8954 ) Ubuntu().install(ssh, packages) From e4ee28efd49ef57cf27f32aeee99e58e70d31c5d Mon Sep 17 00:00:00 2001 From: Mikolaj Grzaslewicz Date: Thu, 7 Sep 2023 11:13:00 +0200 Subject: [PATCH 64/73] JPERF-273 Use SoftAssertions --- .../api/jira/instance/JiraDataCenterPlanIT.kt | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt index f8666e24..e82fa71c 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt @@ -17,6 +17,8 @@ import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApachePro import com.atlassian.performance.tools.ssh.api.SshConnection import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable +import org.assertj.core.api.SoftAssertions +import org.assertj.core.api.SoftAssertions.* import org.junit.After import org.junit.Before import org.junit.Test @@ -128,16 +130,18 @@ class JiraDataCenterPlanIT { .walkTopDown() .map { reports.toPath().relativize(it.toPath()) } .toList() - assertThat(fileTree.map { it.toString() }).contains( - "jira-node-1/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out", - "jira-node-1/~/jpt-jstat.log", - "jira-node-2/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out" - ) - assertThat(fileTree.filter { it.fileName.toString() == "atlassian-jira.log" }) - .`as`("Jira log from $fileTree") - .isNotEmpty - assertThat(fileTree.filter { it.fileName.toString().startsWith("atlassian-jira-gc") }) - .`as`("GC logs from $fileTree") - .isNotEmpty + assertSoftly { + it.assertThat(fileTree.map { it.toString() }).contains( + "jira-node-1/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out", + "jira-node-1/~/jpt-jstat.log", + "jira-node-2/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out" + ) + it.assertThat(fileTree.filter { it.fileName.toString() == "atlassian-jira.log" }) + .`as`("Jira log from $fileTree") + .isNotEmpty + it.assertThat(fileTree.filter { it.fileName.toString().startsWith("atlassian-jira-gc") }) + .`as`("GC logs from $fileTree") + .isNotEmpty + } } } From fa9254c118c4a9c8b51a543b260b2596169458fd Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Thu, 7 Sep 2023 12:33:29 +0200 Subject: [PATCH 65/73] JPERF-273: Switch to Docker image with Ubuntu 22 Fix `DockerIT`. --- .../tools/infrastructure/api/DockerInfrastructure.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index 4bce146a..fbe8ba50 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -88,13 +88,15 @@ internal class DockerInfrastructure( val ports = tcpPorts.map { ExposedPort.tcp(it) } + udpPorts.map { ExposedPort.udp(it) } + ExposedPort.tcp(22) + val imageName = "takeyamajp/ubuntu-sshd" + val imageTag = "ubuntu$ubuntuVersion" docker - .pullImageCmd("rastasheep/ubuntu-sshd") - .withTag(ubuntuVersion) + .pullImageCmd(imageName) + .withTag(imageTag) .exec(PullImageResultCallback()) .awaitCompletion() val createdContainer = docker - .createContainerCmd("rastasheep/ubuntu-sshd:18.04") + .createContainerCmd("$imageName:$imageTag") .withHostConfig( HostConfig() .withPublishAllPorts(true) From 48bb603791d1a009ea12558544f39823cdfaffbe Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Thu, 7 Sep 2023 12:56:21 +0200 Subject: [PATCH 66/73] JPERF-273: Reduce integration test parallelism Perhaps it will consume less disk space in peaks. Try to avoid error on GitHub Actions: ``` com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraServiceDeskDistributionIT > shouldDownloadJiraServiceDesk FAILED java.lang.Exception at PublicJiraServiceDeskDistributionIT.kt:17 Caused by: net.schmizz.sshj.connection.ConnectionException at PublicJiraServiceDeskDistributionIT.kt:17 Caused by: java.util.concurrent.TimeoutException at PublicJiraServiceDeskDistributionIT.kt:17 java.io.IOException: No space left on device com.esotericsoftware.kryo.KryoException: java.io.IOException: No space left on device at com.esotericsoftware.kryo.io.Output.flush(Output.java:165) ``` --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index fba3fe7f..ed7d4ee7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -110,7 +110,7 @@ val testIntegration = task("testIntegration") { filter { include("**/*IT.class") } - maxParallelForks = 5 + maxParallelForks = 2 } tasks["check"].dependsOn(testIntegration) From c46b1f632574c5d8202932550b8e646e1d0a8de9 Mon Sep 17 00:00:00 2001 From: Mikolaj Grzaslewicz Date: Thu, 7 Sep 2023 15:43:06 +0200 Subject: [PATCH 67/73] JPERF-273 Do not run DataCenter and Server plan in parallel Tests were consuming too much space in CI, up to ~15 GB in spikes --- build.gradle.kts | 2 +- ...{JiraDataCenterPlanIT.kt => JiraPlanIT.kt} | 105 ++++++++++++++-- .../api/jira/instance/JiraServerPlanIT.kt | 112 ------------------ 3 files changed, 97 insertions(+), 122 deletions(-) rename src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/{JiraDataCenterPlanIT.kt => JiraPlanIT.kt} (60%) delete mode 100644 src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlanIT.kt diff --git a/build.gradle.kts b/build.gradle.kts index ed7d4ee7..fba3fe7f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -110,7 +110,7 @@ val testIntegration = task("testIntegration") { filter { include("**/*IT.class") } - maxParallelForks = 2 + maxParallelForks = 5 } tasks["check"].dependsOn(testIntegration) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt similarity index 60% rename from src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt rename to src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt index e82fa71c..99782256 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt @@ -14,18 +14,21 @@ import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostSt import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan +import com.atlassian.performance.tools.io.api.resolveSafely import com.atlassian.performance.tools.ssh.api.SshConnection -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.catchThrowable +import org.assertj.core.api.Assertions +import org.assertj.core.api.Assertions.* import org.assertj.core.api.SoftAssertions -import org.assertj.core.api.SoftAssertions.* +import org.assertj.core.api.SoftAssertions.assertSoftly import org.junit.After import org.junit.Before import org.junit.Test import java.nio.file.Files -import java.time.Duration.ofMinutes +import java.nio.file.Paths +import java.time.Duration +import java.time.Instant -class JiraDataCenterPlanIT { +class JiraPlanIT { private lateinit var infrastructure: DockerInfrastructure private val dataset = Datasets.SmallJiraEightDataset @@ -90,12 +93,15 @@ class JiraDataCenterPlanIT { @Test - fun shouldProvideLogsToDiagnoseFailure() { + fun shouldProvideDataCenterLogsToDiagnoseFailure() { // given class FailingHook : PostStartHook { override fun call(ssh: SshConnection, jira: StartedJira, hooks: PostStartHooks, reports: Reports) { val installed = jira.installed - ssh.execute("${installed.jdk.use()}; ${installed.installation.path}/bin/stop-jira.sh", ofMinutes(1)) + ssh.execute( + "${installed.jdk.use()}; ${installed.installation.path}/bin/stop-jira.sh", + Duration.ofMinutes(1) + ) throw Exception("Failing deliberately after Jira started") } } @@ -124,13 +130,13 @@ class JiraDataCenterPlanIT { val reports = dcPlan.report().downloadTo(Files.createTempDirectory("jira-dc-plan-")) // then - assertThat(thrown).hasMessageStartingWith("Failing deliberately") - assertThat(reports).isDirectory() val fileTree = reports .walkTopDown() .map { reports.toPath().relativize(it.toPath()) } .toList() assertSoftly { + it.assertThat(thrown).hasMessageStartingWith("Failing deliberately") + it.assertThat(reports).isDirectory() it.assertThat(fileTree.map { it.toString() }).contains( "jira-node-1/atlassian-jira-software-$jiraVersion-standalone/logs/catalina.out", "jira-node-1/~/jpt-jstat.log", @@ -144,4 +150,85 @@ class JiraDataCenterPlanIT { .isNotEmpty } } + + + @Test + fun shouldStartJiraServerWithHooks() { + // given + val hooks = PreInstallHooks.default() + .also { dataset.hookDataUpgrade(it.postStart) } + val nodePlan = JiraNodePlan.Builder(infrastructure) + .hooks(hooks) + .installation( + ParallelInstallation( + jiraHomeSource = JiraHomePackage(dataset.jiraHome), + productDistribution = jiraDistribution, + jdk = AdoptOpenJDK() + ) + ) + .start(JiraLaunchScript()) + .hooks(hooks) + .build() + val instanceHooks = PreInstanceHooks.default() + .also { dataset.hookMysql(it, infrastructure) } + val jiraServerPlan = JiraServerPlan.Builder(infrastructure) + .plan(nodePlan) + .hooks(instanceHooks) + .build() + + // when + val jiraServer = try { + jiraServerPlan.materialize() + } catch (e: Exception) { + debug(jiraServerPlan, e) + } + val reports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) + + // then + val theNode = jiraServer.nodes.single() + val serverXml = theNode + .installed + .installation + .resolve("conf/server.xml") + .download(Files.createTempFile("downloaded-config", ".xml")) + + assertSoftly { + it.assertThat(serverXml.readText()).contains(" Date: Mon, 11 Sep 2023 10:51:35 +0200 Subject: [PATCH 68/73] JPERF-273 Prefer HttpNode instead of using URI for load balancer --- .../api/jira/instance/JiraDataCenterPlan.kt | 12 +++--------- .../infrastructure/api/jira/instance/JiraInstance.kt | 5 +++-- .../api/jira/instance/JiraServerPlan.kt | 6 +++--- .../api/loadbalancer/ApacheProxyPlan.kt | 10 ++-------- .../infrastructure/api/loadbalancer/LoadBalancer.kt | 3 ++- .../api/loadbalancer/LoadBalancerPlan.kt | 4 ++-- 6 files changed, 15 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt index 47710fa7..b0e5f1e4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt @@ -2,16 +2,12 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan -import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancer import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancerPlan import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom -import java.net.URI import java.time.Duration -import java.util.function.Consumer import kotlin.streams.asStream import kotlin.streams.toList @@ -36,7 +32,6 @@ class JiraDataCenterPlan private constructor( val started = installed.map { it.start(reports) } val instance = JiraDataCenter(started, balancer) instanceHooks.postInstance.call(instance, reports) - balancer.waitUntilHealthy(loadBalancingPatience) return instance } @@ -69,10 +64,9 @@ class JiraDataCenterPlan private constructor( private class JiraDataCenter( override val nodes: List, - private val loadBalancer: LoadBalancer + loadBalancer: HttpNode ) : JiraInstance { - override val address: URI - get() = loadBalancer.uri + override val address = loadBalancer } class Builder( @@ -98,4 +92,4 @@ class JiraDataCenterPlan private constructor( fun build(): JiraInstancePlan = JiraDataCenterPlan(nodePlans, instanceHooks, balancerPlan) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt index 173b48ac..f98b4553 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt @@ -1,9 +1,10 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import java.net.URI interface JiraInstance { - val address: URI + val address: HttpNode val nodes: List -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt index 284f160c..348ad7e7 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt @@ -1,9 +1,9 @@ package com.atlassian.performance.tools.infrastructure.api.jira.instance +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom -import java.net.URI class JiraServerPlan private constructor( private val plan: JiraNodePlan, @@ -28,7 +28,7 @@ class JiraServerPlan private constructor( private class JiraServer( node: StartedJira ) : JiraInstance { - override val address: URI = node.installed.http.addressPublicly() + override val address: HttpNode = node.installed.http override val nodes: List = listOf(node) } @@ -47,4 +47,4 @@ class JiraServerPlan private constructor( fun build(): JiraInstancePlan = JiraServerPlan(plan, hooks) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt index c3c498aa..6e5220d8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt @@ -20,7 +20,7 @@ class ApacheProxyPlan( private val configPath = "/etc/apache2/sites-enabled/000-default.conf" - override fun materialize(nodes: List, hooks: List): LoadBalancer { + override fun materialize(nodes: List, hooks: List): HttpNode { val proxyNode = serverRoom.serveHttp("apache-proxy") IdempotentAction("Installing and configuring apache load balancer") { proxyNode.tcp.ssh.newConnection().use { connection -> @@ -29,7 +29,7 @@ class ApacheProxyPlan( }.retry(2, ExponentialBackoff(Duration.ofSeconds(5))) val balancerEndpoint = proxyNode.addressPrivately() hooks.forEach { it.insert(InjectProxy(balancerEndpoint)) } - return ApacheProxy(balancerEndpoint) + return proxyNode } private fun tryToProvision(ssh: SshConnection, nodes: List, proxyNode: HttpNode) { @@ -60,12 +60,6 @@ class ApacheProxyPlan( connection.execute("echo \"$line\" | sudo tee -a $configPath") } - private class ApacheProxy( - override val uri: URI - ) : LoadBalancer { - override fun waitUntilHealthy(timeout: Duration) {} - } - private class InjectProxy( private val proxy: URI ) : PreStartHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancer.kt index 4fcc35db..93df5246 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancer.kt @@ -3,7 +3,8 @@ package com.atlassian.performance.tools.infrastructure.api.loadbalancer import java.net.URI import java.time.Duration +@Deprecated("Use com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode instead.") interface LoadBalancer { fun waitUntilHealthy(timeout: Duration) val uri: URI -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt index c0d9cca6..bc40a24a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt @@ -4,5 +4,5 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks interface LoadBalancerPlan { - fun materialize(nodes: List, hooks: List): LoadBalancer -} \ No newline at end of file + fun materialize(nodes: List, hooks: List): HttpNode +} From 34fdce5e9c75e44bcbc0e2fe1733ebbab094cf4d Mon Sep 17 00:00:00 2001 From: Mikolaj Grzaslewicz Date: Mon, 11 Sep 2023 10:55:14 +0200 Subject: [PATCH 69/73] JPERF-273 Stop adding suffix '/' in HttpNode Consumers should provide a working path --- .../tools/infrastructure/api/jira/install/HttpNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt index e7219f85..c4d0a9b4 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/HttpNode.kt @@ -14,6 +14,6 @@ class HttpNode( private fun address(ip: String, userInfo: String = ""): URI { val scheme = if (supportsTls) "https" else "http" - return URI("$scheme://$userInfo$ip:${tcp.port}$basePath/") + return URI("$scheme://$userInfo$ip:${tcp.port}$basePath") } } From 000ce569f0332f958fe94241dc90ffa24183d1ba Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 11 Sep 2023 13:01:24 +0200 Subject: [PATCH 70/73] JPERF-273: Fix sudo when editing apache config Fix errors like: ``` java.lang.Exception: Failed to Installing and configuring apache load balancer despite 2 attempts at com.atlassian.performance.tools.jvmtasks.api.IdempotentAction.retry(IdempotentAction.kt:42) at com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan.materialize(ApacheProxyPlan.kt:29) at com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraDataCenterPlan.materialize(JiraDataCenterPlan.kt:30) at com.atlassian.performance.tools.awsinfrastructure.api.jira.HooksDataCenterFormulaIT$shouldProvisionDc$1.invoke(HooksDataCenterFormulaIT.kt:121) at com.atlassian.performance.tools.awsinfrastructure.api.jira.HooksDataCenterFormulaIT$shouldProvisionDc$1.invoke(HooksDataCenterFormulaIT.kt:41) at com.atlassian.performance.tools.awsinfrastructure.api.jira.HooksDataCenterFormulaIT.makeFailureObservable(HooksDataCenterFormulaIT.kt:70) at com.atlassian.performance.tools.awsinfrastructure.api.jira.HooksDataCenterFormulaIT.shouldProvisionDc(HooksDataCenterFormulaIT.kt:120) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175) at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) at java.lang.Thread.run(Thread.java:750) Suppressed: java.lang.RuntimeException: Potential Jira problems found in workspace: {} at com.atlassian.performance.tools.awsinfrastructure.api.jira.HooksDataCenterFormulaIT.makeFailureObservable(HooksDataCenterFormulaIT.kt:74) ... 48 more Caused by: java.lang.Exception: Error while executing sed -i -r 's/Listen 80/Listen 80/g' /etc/apache2/ports.conf. Exit status code SshResult(exitStatus=4, output=, errorOutput=sed: couldn't open temporary file /etc/apache2/sed3Zlw2Y: Permission denied ) at com.atlassian.performance.tools.ssh.SshjConnection.execute(SshjConnection.kt:40) at com.atlassian.performance.tools.ssh.api.SshConnection.execute(SshConnection.kt:27) at com.atlassian.performance.tools.infrastructure.api.Sed.replace(Sed.kt:14) at com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan.tryToProvision(ApacheProxyPlan.kt:37) at com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan.access$tryToProvision(ApacheProxyPlan.kt:17) at com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan$materialize$1.invoke(ApacheProxyPlan.kt:27) at com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan$materialize$1.invoke(ApacheProxyPlan.kt:17) at com.atlassian.performance.tools.jvmtasks.api.IdempotentAction.retry(IdempotentAction.kt:28) ... 53 more ``` --- .../com/atlassian/performance/tools/infrastructure/api/Sed.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Sed.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Sed.kt index 082c6a05..f6ac9766 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Sed.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/Sed.kt @@ -11,6 +11,6 @@ class Sed { ) { val escapedExpression = expression.replace("/", "\\/") val escapedOutput = output.replace("/", "\\/") - connection.execute("sed -i -r 's/$escapedExpression/$escapedOutput/g' $file") + connection.execute("sudo sed -i -r 's/$escapedExpression/$escapedOutput/g' $file") } } From 4eea592a036e2b655846df6699d07aae7a9a404e Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 11 Sep 2023 13:16:26 +0200 Subject: [PATCH 71/73] JPERF-273: Assert on private address --- .../infrastructure/api/database/DockerMysqlServer.kt | 2 +- .../infrastructure/api/jira/instance/JiraPlanIT.kt | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt index c84f4967..5050adcc 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt @@ -101,7 +101,7 @@ class DockerMysqlServer private constructor( override fun call(instance: JiraInstance, hooks: PostInstanceHooks, reports: Reports) { ssh.newConnection().use { ssh -> val db = "jiradb" - val update = "UPDATE $db.propertystring SET propertyvalue = '${instance.address}'" + val update = "UPDATE $db.propertystring SET propertyvalue = '${instance.address.addressPrivately()}'" val where = "WHERE id IN (select id from $db.propertyentry where property_key like '%baseurl%')" client.runSql(ssh, "$update $where;") } diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt index 99782256..cc7db7e7 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt @@ -16,9 +16,8 @@ import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan import com.atlassian.performance.tools.io.api.resolveSafely import com.atlassian.performance.tools.ssh.api.SshConnection -import org.assertj.core.api.Assertions -import org.assertj.core.api.Assertions.* -import org.assertj.core.api.SoftAssertions +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable import org.assertj.core.api.SoftAssertions.assertSoftly import org.junit.After import org.junit.Before @@ -85,10 +84,12 @@ class JiraPlanIT { .download(Files.createTempFile("downloaded-config", ".xml")) assertThat(serverXml.readText()).contains(" - ssh.execute("wget ${dataCenter.address}") + val fakeVu = infrastructure.serveSsh() + fakeVu.newConnection().use { ssh -> + ssh.execute("wget ${dataCenter.address.addressPrivately()}") } } + dataCenter.address.addressPublicly().toURL().readText() } From 0f871b741a2f3790c6a147a4f49bd6f5d7c18287 Mon Sep 17 00:00:00 2001 From: Maciej Kwidzinski Date: Mon, 11 Sep 2023 13:23:46 +0200 Subject: [PATCH 72/73] JPERF-273: Assert JiraInstance access --- .../api/jira/instance/JiraPlanIT.kt | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt index cc7db7e7..2d2dbc38 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt @@ -76,6 +76,7 @@ class JiraPlanIT { val dataCenter = dcPlan.materialize() // then + assertJiraAccessible(dataCenter) dataCenter.nodes.forEach { node -> val installed = node.installed val serverXml = installed @@ -84,12 +85,7 @@ class JiraPlanIT { .download(Files.createTempFile("downloaded-config", ".xml")) assertThat(serverXml.readText()).contains(" - ssh.execute("wget ${dataCenter.address.addressPrivately()}") - } } - dataCenter.address.addressPublicly().toURL().readText() } @@ -186,6 +182,7 @@ class JiraPlanIT { val reports = jiraServerPlan.report().downloadTo(Files.createTempDirectory("jira-server-plan-")) // then + assertJiraAccessible(jiraServer) val theNode = jiraServer.nodes.single() val serverXml = theNode .installed @@ -216,6 +213,19 @@ class JiraPlanIT { } } + private fun assertJiraAccessible(jira: JiraInstance) { + val fakeVu = infrastructure.serveSsh() + fakeVu.newConnection().use { ssh -> + ssh.execute("wget ${jira.address.addressPrivately()}") + } + try { + val response = jira.address.addressPublicly().toURL().readText() + assertThat(response).contains(" Date: Mon, 11 Sep 2023 15:14:18 +0200 Subject: [PATCH 73/73] JPERF-273 Move hook functionality out of API. It's not ready yet --- .../infrastructure/database/MysqlFiveConnector.kt | 7 +++---- .../database/MysqlFiveDotSevenJiraConfig.kt | 4 ++-- .../{api => hookapi}/database/DatabaseIpConfig.kt | 8 ++++---- .../{api => hookapi}/database/DockerMysqlServer.kt | 14 ++++++++------ .../jira/install/hook/AsyncProfilerHook.kt | 6 +++--- .../jira/install/hook/DisabledAutoBackup.kt | 4 +++- .../jira/install/hook/JiraHomeProperty.kt | 4 +++- .../{api => hookapi}/jira/install/hook/JiraLogs.kt | 2 +- .../jira/install/hook/JvmConfig.kt | 4 +++- .../jira/install/hook/LateUbuntuSysstat.kt | 6 +++--- .../jira/install/hook/PostInstallHook.kt | 2 +- .../jira/install/hook/PostInstallHooks.kt | 4 ++-- .../jira/install/hook/PreInstallHook.kt | 3 +-- .../jira/install/hook/PreInstallHooks.kt | 2 +- .../jira/install/hook/SystemLog.kt | 4 +++- .../jira/instance/DefaultClusterProperties.kt | 6 +++--- .../jira/instance/JiraDataCenterPlan.kt | 8 ++++---- .../{api => hookapi}/jira/instance/JiraInstance.kt | 3 +-- .../jira/instance/JiraInstancePlan.kt | 4 ++-- .../{api => hookapi}/jira/instance/JiraNodePlan.kt | 6 +++--- .../jira/instance/JiraServerPlan.kt | 4 ++-- .../jira/instance/PostInstanceHook.kt | 2 +- .../jira/instance/PostInstanceHooks.kt | 2 +- .../jira/instance/PreInstanceHook.kt | 4 ++-- .../jira/instance/PreInstanceHooks.kt | 4 ++-- .../jira/sharedhome/NfsSharedHome.kt | 12 ++++++------ .../jira/sharedhome/SambaSharedHome.kt | 13 ++++++------- .../{api => hookapi}/jira/start/hook/AccessLogs.kt | 2 +- .../{api => hookapi}/jira/start/hook/JstatHook.kt | 2 +- .../jira/start/hook/PostStartHook.kt | 2 +- .../jira/start/hook/PostStartHooks.kt | 2 +- .../jira/start/hook/PreStartHook.kt | 2 +- .../jira/start/hook/PreStartHooks.kt | 2 +- .../jira/start/hook/RestUpgrade.kt | 6 +++--- .../loadbalancer/ApacheProxyPlan.kt | 10 +++++----- .../loadbalancer/LoadBalancerPlan.kt | 4 ++-- .../{api => hookapi}/network/HttpServerRoom.kt | 4 ++-- .../jira/install/hook/HookedJiraInstallation.kt | 2 +- .../jira/install/hook/ProfilerHook.kt | 10 +++++----- .../jira/install/hook/SplunkForwarderHook.kt | 4 ++-- .../jira/start/hook/HookedJiraStart.kt | 2 +- .../performance/tools/infrastructure/Datasets.kt | 8 ++++---- .../infrastructure/api/DockerInfrastructure.kt | 4 ++-- .../api/jira/install/hook/PreInstallHooksTest.kt | 2 ++ .../infrastructure/api/jira/instance/JiraPlanIT.kt | 11 ++++++----- 45 files changed, 115 insertions(+), 106 deletions(-) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/database/DatabaseIpConfig.kt (77%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/database/DockerMysqlServer.kt (86%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/AsyncProfilerHook.kt (88%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/DisabledAutoBackup.kt (65%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/JiraHomeProperty.kt (69%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/JiraLogs.kt (93%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/JvmConfig.kt (79%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/LateUbuntuSysstat.kt (83%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/PostInstallHook.kt (88%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/PostInstallHooks.kt (90%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/PreInstallHook.kt (85%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/PreInstallHooks.kt (93%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/install/hook/SystemLog.kt (65%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/DefaultClusterProperties.kt (70%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/JiraDataCenterPlan.kt (90%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/JiraInstance.kt (72%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/JiraInstancePlan.kt (68%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/JiraNodePlan.kt (91%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/JiraServerPlan.kt (90%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/PostInstanceHook.kt (84%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/PostInstanceHooks.kt (90%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/PreInstanceHook.kt (68%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/instance/PreInstanceHooks.kt (81%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/sharedhome/NfsSharedHome.kt (82%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/sharedhome/SambaSharedHome.kt (85%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/AccessLogs.kt (87%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/JstatHook.kt (89%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/PostStartHook.kt (88%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/PostStartHooks.kt (92%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/PreStartHook.kt (88%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/PreStartHooks.kt (92%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/jira/start/hook/RestUpgrade.kt (95%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/loadbalancer/ApacheProxyPlan.kt (90%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/loadbalancer/LoadBalancerPlan.kt (53%) rename src/main/kotlin/com/atlassian/performance/tools/infrastructure/{api => hookapi}/network/HttpServerRoom.kt (67%) diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt index 487a4c9c..06cc4388 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveConnector.kt @@ -1,13 +1,12 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.jvmtasks.api.StaticBackoff import com.atlassian.performance.tools.ssh.api.SshConnection -import java.time.Duration import java.time.Duration.ofSeconds /** @@ -28,4 +27,4 @@ class MysqlFiveConnector : PostInstallHook { ssh.execute("tar -xzf mysql-connector-java-5.1.40.tar.gz") ssh.execute("cp mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${jira.installation.path}/lib") } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt index 8f0f2d7a..99eb410d 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/database/MysqlFiveDotSevenJiraConfig.kt @@ -2,8 +2,8 @@ package com.atlassian.performance.tools.infrastructure.database import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.infrastructure.api.os.RemotePath diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DatabaseIpConfig.kt similarity index 77% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DatabaseIpConfig.kt index 950e73a4..565e67bf 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DatabaseIpConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DatabaseIpConfig.kt @@ -1,9 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.api.database +package com.atlassian.performance.tools.infrastructure.hookapi.database import com.atlassian.performance.tools.infrastructure.api.Sed import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.report.StaticReport import com.atlassian.performance.tools.ssh.api.SshConnection @@ -27,4 +27,4 @@ class DatabaseIpConfig( file = dbConfigXml ) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DockerMysqlServer.kt similarity index 86% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DockerMysqlServer.kt index 5050adcc..9ed15edd 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/database/DockerMysqlServer.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/database/DockerMysqlServer.kt @@ -1,16 +1,18 @@ -package com.atlassian.performance.tools.infrastructure.api.database +package com.atlassian.performance.tools.infrastructure.hookapi.database import com.atlassian.performance.tools.infrastructure.api.dataset.DatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.JiraInstance -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.database.* +import com.atlassian.performance.tools.infrastructure.database.Mysql +import com.atlassian.performance.tools.infrastructure.database.SshMysqlClient +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.JiraInstance +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PostInstanceHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PostInstanceHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PreInstanceHook import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/AsyncProfilerHook.kt similarity index 88% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/AsyncProfilerHook.kt index 453ba963..c17a6a96 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/AsyncProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/AsyncProfilerHook.kt @@ -1,11 +1,11 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Report import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.ssh.api.SshConnection import java.net.URI diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/DisabledAutoBackup.kt similarity index 65% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/DisabledAutoBackup.kt index 164da451..50b34110 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/DisabledAutoBackup.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/DisabledAutoBackup.kt @@ -1,7 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.ssh.api.SshConnection class DisabledAutoBackup : PostInstallHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraHomeProperty.kt similarity index 69% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraHomeProperty.kt index b09991b5..cbd517c8 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraHomeProperty.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraHomeProperty.kt @@ -1,7 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.ssh.api.SshConnection class JiraHomeProperty : PostInstallHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraLogs.kt similarity index 93% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraLogs.kt index 7d544f19..5758e5bb 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JiraLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JiraLogs.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Report diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JvmConfig.kt similarity index 79% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JvmConfig.kt index 3fe4ab97..dbaaa717 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/JvmConfig.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/JvmConfig.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraGcLog import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig @@ -6,6 +6,8 @@ import com.atlassian.performance.tools.infrastructure.api.jira.SetenvSh import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.ssh.api.SshConnection class JvmConfig( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/LateUbuntuSysstat.kt similarity index 83% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/LateUbuntuSysstat.kt index 2404e567..0a3c89c6 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/LateUbuntuSysstat.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/LateUbuntuSysstat.kt @@ -1,14 +1,14 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.Iostat import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.api.os.OsMetric import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu import com.atlassian.performance.tools.infrastructure.api.os.Vmstat +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHook.kt similarity index 88% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHook.kt index c95cd0cb..9eb4fa2b 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHook.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHooks.kt similarity index 90% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHooks.kt index 37088763..41277b3e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PostInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PostInstallHooks.kt @@ -1,9 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraNodeConfig import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHooks import com.atlassian.performance.tools.infrastructure.jira.install.hook.ProfilerHook import com.atlassian.performance.tools.infrastructure.jira.install.hook.SplunkForwarderHook import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHook.kt similarity index 85% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHook.kt index 6998f149..49be4fc9 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHook.kt @@ -1,9 +1,8 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.ssh.api.SshConnection -import org.apache.http.HttpHost /** * Intercepts a call before Jira is installed. diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHooks.kt similarity index 93% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHooks.kt index d748580f..db6ead0c 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/PreInstallHooks.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/SystemLog.kt similarity index 65% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/SystemLog.kt index 21904606..42841fc9 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/SystemLog.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/install/hook/SystemLog.kt @@ -1,8 +1,10 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.install.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.ssh.api.SshConnection class SystemLog : PreInstallHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/DefaultClusterProperties.kt similarity index 70% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/DefaultClusterProperties.kt index ab342f07..2561eb37 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/DefaultClusterProperties.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/DefaultClusterProperties.kt @@ -1,8 +1,8 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.jira.instance.ClusterProperties import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraDataCenterPlan.kt similarity index 90% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraDataCenterPlan.kt index b0e5f1e4..6b5b652a 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraDataCenterPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraDataCenterPlan.kt @@ -1,12 +1,12 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan -import com.atlassian.performance.tools.infrastructure.api.loadbalancer.LoadBalancerPlan -import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.hookapi.loadbalancer.ApacheProxyPlan +import com.atlassian.performance.tools.infrastructure.hookapi.loadbalancer.LoadBalancerPlan +import com.atlassian.performance.tools.infrastructure.hookapi.network.HttpServerRoom import java.time.Duration import kotlin.streams.asStream import kotlin.streams.toList diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstance.kt similarity index 72% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstance.kt index f98b4553..73308d21 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstance.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstance.kt @@ -1,8 +1,7 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import java.net.URI interface JiraInstance { val address: HttpNode diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstancePlan.kt similarity index 68% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstancePlan.kt index 2b80ac64..02d8c3f5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraInstancePlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraInstancePlan.kt @@ -1,8 +1,8 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports interface JiraInstancePlan { fun materialize(): JiraInstance fun report(): Reports -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraNodePlan.kt similarity index 91% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraNodePlan.kt index 922ddd28..828ce080 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraNodePlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraNodePlan.kt @@ -1,14 +1,14 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.EmptyJiraHome import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart import com.atlassian.performance.tools.infrastructure.api.jvm.OracleJDK -import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.hookapi.network.HttpServerRoom import com.atlassian.performance.tools.infrastructure.jira.install.hook.HookedJiraInstallation import com.atlassian.performance.tools.infrastructure.jira.start.hook.HookedJiraStart import net.jcip.annotations.NotThreadSafe diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraServerPlan.kt similarity index 90% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraServerPlan.kt index 348ad7e7..df3ad0db 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraServerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/JiraServerPlan.kt @@ -1,9 +1,9 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.hookapi.network.HttpServerRoom class JiraServerPlan private constructor( private val plan: JiraNodePlan, diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHook.kt similarity index 84% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHook.kt index 42e3442c..f680bf49 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHook.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHooks.kt similarity index 90% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHooks.kt index b56147ae..f9480026 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PostInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PostInstanceHooks.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import java.util.* diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHook.kt similarity index 68% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHook.kt index 10de8f1e..73feac8e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHook.kt @@ -1,6 +1,6 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports interface PreInstanceHook { diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHooks.kt similarity index 81% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHooks.kt index f732f6df..f9ca9905 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/PreInstanceHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/instance/PreInstanceHooks.kt @@ -1,6 +1,6 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.instance +package com.atlassian.performance.tools.infrastructure.hookapi.jira.instance -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import java.util.* import java.util.concurrent.ConcurrentLinkedQueue diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/NfsSharedHome.kt similarity index 82% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/NfsSharedHome.kt index 99f7072e..2638f265 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/NfsSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/NfsSharedHome.kt @@ -1,17 +1,17 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome +package com.atlassian.performance.tools.infrastructure.hookapi.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.Networked import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PostInstanceHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.jira.sharedhome.SharedHomeProperty import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/SambaSharedHome.kt similarity index 85% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/SambaSharedHome.kt index da4d8c29..d92f1590 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/sharedhome/SambaSharedHome.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/sharedhome/SambaSharedHome.kt @@ -1,14 +1,13 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.sharedhome +package com.atlassian.performance.tools.infrastructure.hookapi.jira.sharedhome import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomeSource import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PostInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHook -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PostInstanceHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PreInstanceHook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/AccessLogs.kt similarity index 87% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/AccessLogs.kt index c2c30a78..1063e810 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/AccessLogs.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/AccessLogs.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/JstatHook.kt similarity index 89% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/JstatHook.kt index f1e15be5..3f7d6adb 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/JstatHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/JstatHook.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHook.kt similarity index 88% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHook.kt index ee867e14..a8392e41 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHook.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHooks.kt similarity index 92% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHooks.kt index 77671948..bb2b6455 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PostStartHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PostStartHooks.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHook.kt similarity index 88% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHook.kt index 0123305e..5313aeb6 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHook.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHooks.kt similarity index 92% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHooks.kt index bc3082f4..b5acd2f1 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/PreStartHooks.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/PreStartHooks.kt @@ -1,4 +1,4 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/RestUpgrade.kt similarity index 95% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/RestUpgrade.kt index 3762f7d2..c949f786 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/start/hook/RestUpgrade.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/jira/start/hook/RestUpgrade.kt @@ -1,11 +1,11 @@ -package com.atlassian.performance.tools.infrastructure.api.jira.start.hook +package com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.JiraLogs import com.atlassian.performance.tools.infrastructure.api.jira.report.FileListing import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira import com.atlassian.performance.tools.infrastructure.api.jvm.ThreadDump +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.JiraLogs import com.atlassian.performance.tools.infrastructure.jira.report.JiraLandingPage import com.atlassian.performance.tools.ssh.api.SshConnection import java.net.URI @@ -86,4 +86,4 @@ class RestUpgrade( ) } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/ApacheProxyPlan.kt similarity index 90% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/ApacheProxyPlan.kt index 6e5220d8..4f83c125 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/ApacheProxyPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/ApacheProxyPlan.kt @@ -1,13 +1,13 @@ -package com.atlassian.performance.tools.infrastructure.api.loadbalancer +package com.atlassian.performance.tools.infrastructure.hookapi.loadbalancer import com.atlassian.performance.tools.infrastructure.api.Sed -import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks -import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.network.HttpServerRoom import com.atlassian.performance.tools.infrastructure.api.os.Ubuntu +import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.jvmtasks.api.ExponentialBackoff import com.atlassian.performance.tools.jvmtasks.api.IdempotentAction import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/LoadBalancerPlan.kt similarity index 53% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/LoadBalancerPlan.kt index bc40a24a..fde4839e 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/loadbalancer/LoadBalancerPlan.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/loadbalancer/LoadBalancerPlan.kt @@ -1,7 +1,7 @@ -package com.atlassian.performance.tools.infrastructure.api.loadbalancer +package com.atlassian.performance.tools.infrastructure.hookapi.loadbalancer import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHooks interface LoadBalancerPlan { fun materialize(nodes: List, hooks: List): HttpNode diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/network/HttpServerRoom.kt similarity index 67% rename from src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt rename to src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/network/HttpServerRoom.kt index 89316ba6..7ca04eb1 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/api/network/HttpServerRoom.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/hookapi/network/HttpServerRoom.kt @@ -1,8 +1,8 @@ -package com.atlassian.performance.tools.infrastructure.api.network +package com.atlassian.performance.tools.infrastructure.hookapi.network import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode interface HttpServerRoom { fun serveHttp(name: String): HttpNode -} \ No newline at end of file +} diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt index 89c2ac7d..0b7b7341 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/HookedJiraInstallation.kt @@ -3,7 +3,7 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira import com.atlassian.performance.tools.infrastructure.api.jira.install.JiraInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports class HookedJiraInstallation( diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt index 3ecd6098..ec6d4d93 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/ProfilerHook.kt @@ -1,13 +1,13 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHook import com.atlassian.performance.tools.infrastructure.api.profiler.Profiler import com.atlassian.performance.tools.infrastructure.jira.report.RemoteMonitoringProcessReport import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt index 0baf1797..361872d5 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/install/hook/SplunkForwarderHook.kt @@ -1,8 +1,8 @@ package com.atlassian.performance.tools.infrastructure.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.InstalledJira -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHook -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PostInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PostInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.splunk.SplunkForwarder import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt index 73d02676..8fc68b07 100644 --- a/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt +++ b/src/main/kotlin/com/atlassian/performance/tools/infrastructure/jira/start/hook/HookedJiraStart.kt @@ -4,7 +4,7 @@ import com.atlassian.performance.tools.infrastructure.api.jira.install.Installed import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraStart import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PreStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PreStartHooks class HookedJiraStart( private val start: JiraStart, diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt index 6658dac5..e7bf8690 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/Datasets.kt @@ -1,11 +1,11 @@ package com.atlassian.performance.tools.infrastructure -import com.atlassian.performance.tools.infrastructure.api.database.DockerMysqlServer +import com.atlassian.performance.tools.infrastructure.hookapi.database.DockerMysqlServer import com.atlassian.performance.tools.infrastructure.api.dataset.HttpDatasetPackage import com.atlassian.performance.tools.infrastructure.api.jira.JiraLaunchTimeouts -import com.atlassian.performance.tools.infrastructure.api.jira.instance.PreInstanceHooks -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.RestUpgrade +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.PreInstanceHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.RestUpgrade import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom import java.net.URI import java.time.Duration diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt index fbe8ba50..2c13a576 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/DockerInfrastructure.kt @@ -2,7 +2,7 @@ package com.atlassian.performance.tools.infrastructure.api import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode -import com.atlassian.performance.tools.infrastructure.api.network.HttpServerRoom +import com.atlassian.performance.tools.infrastructure.hookapi.network.HttpServerRoom import com.atlassian.performance.tools.infrastructure.api.network.Networked import com.atlassian.performance.tools.infrastructure.api.network.SshServerRoom import com.atlassian.performance.tools.infrastructure.api.network.TcpServerRoom @@ -180,4 +180,4 @@ internal class DockerInfrastructure( ?: break } } -} \ No newline at end of file +} diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt index b94cfca2..83a6148f 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/install/hook/PreInstallHooksTest.kt @@ -3,6 +3,8 @@ package com.atlassian.performance.tools.infrastructure.api.jira.install.hook import com.atlassian.performance.tools.infrastructure.api.jira.install.HttpNode import com.atlassian.performance.tools.infrastructure.api.jira.install.TcpNode import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.mock.UnimplementedSshConnection import com.atlassian.performance.tools.ssh.api.Ssh import com.atlassian.performance.tools.ssh.api.SshConnection diff --git a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt index 2d2dbc38..17524180 100644 --- a/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt +++ b/src/test/kotlin/com/atlassian/performance/tools/infrastructure/api/jira/instance/JiraPlanIT.kt @@ -5,15 +5,16 @@ import com.atlassian.performance.tools.infrastructure.api.DockerInfrastructure import com.atlassian.performance.tools.infrastructure.api.distribution.PublicJiraSoftwareDistribution import com.atlassian.performance.tools.infrastructure.api.jira.JiraHomePackage import com.atlassian.performance.tools.infrastructure.api.jira.install.ParallelInstallation -import com.atlassian.performance.tools.infrastructure.api.jira.install.hook.PreInstallHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.install.hook.PreInstallHooks import com.atlassian.performance.tools.infrastructure.api.jira.report.Reports -import com.atlassian.performance.tools.infrastructure.api.jira.sharedhome.SambaSharedHome +import com.atlassian.performance.tools.infrastructure.hookapi.jira.sharedhome.SambaSharedHome import com.atlassian.performance.tools.infrastructure.api.jira.start.JiraLaunchScript import com.atlassian.performance.tools.infrastructure.api.jira.start.StartedJira -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHook -import com.atlassian.performance.tools.infrastructure.api.jira.start.hook.PostStartHooks +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHook +import com.atlassian.performance.tools.infrastructure.hookapi.jira.start.hook.PostStartHooks import com.atlassian.performance.tools.infrastructure.api.jvm.AdoptOpenJDK -import com.atlassian.performance.tools.infrastructure.api.loadbalancer.ApacheProxyPlan +import com.atlassian.performance.tools.infrastructure.hookapi.loadbalancer.ApacheProxyPlan +import com.atlassian.performance.tools.infrastructure.hookapi.jira.instance.* import com.atlassian.performance.tools.io.api.resolveSafely import com.atlassian.performance.tools.ssh.api.SshConnection import org.assertj.core.api.Assertions.assertThat