From 611b2c0e6ea26eb748e00b03764d06f7ee398638 Mon Sep 17 00:00:00 2001 From: az Date: Sat, 29 Apr 2023 19:35:09 +0200 Subject: [PATCH] [skip ci] re-open ssh session by RemoteUbuntuProcessor.kt if required --- .../provs/framework/core/Prov.kt | 2 + .../framework/core/processors/Processor.kt | 5 ++- .../core/processors/RemoteUbuntuProcessor.kt | 9 ++-- .../ContainerUbuntuHostProcessorTest.kt | 43 +++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt index 95c1588..c995d27 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Prov.kt @@ -271,6 +271,8 @@ open class Prov protected constructor( previousLevel = -1 exit = false initProgress() + + processor.open() } // pre-handling diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt index 7138d8f..07ef609 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/Processor.kt @@ -2,10 +2,13 @@ package org.domaindrivenarchitecture.provs.framework.core.processors interface Processor { + fun open() { + // no action needed for most processors; otherwise, overwrite this method in the implementing class + } fun exec(vararg args: String): ProcessResult fun execNoLog(vararg args: String): ProcessResult fun close() { - // no action needed for most processors; if action is needed when closing, this method must be overwritten in the subclass + // no action needed for most processors; otherwise, overwrite this method in the implementing class } } diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt index ead6482..a8d8f7f 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/RemoteUbuntuProcessor.kt @@ -21,17 +21,20 @@ import java.util.concurrent.TimeUnit * Executes task on a remote machine. * Attention: host key is currently not being verified */ -class RemoteProcessor(host: InetAddress, user: String, password: Secret? = null) : Processor { +class RemoteProcessor(val host: InetAddress, val user: String, val password: Secret? = null) : Processor { companion object { @Suppress("JAVA_CLASS_ON_COMPANION") private val log = LoggerFactory.getLogger(javaClass.enclosingClass) } - private val ssh = SSHClient() + private var ssh = SSHClient() - init { + override fun open() { try { + // always create a new instance as old one might be closed + ssh = SSHClient() + log.info("Connecting to $host with user: $user with " + if (password != null) "password" else "ssh-key") ssh.loadKnownHosts() diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt index 520e9e9..c813c34 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/core/processors/ContainerUbuntuHostProcessorTest.kt @@ -1,9 +1,14 @@ package org.domaindrivenarchitecture.provs.framework.core.processors +import org.domaindrivenarchitecture.provs.framework.core.* import org.domaindrivenarchitecture.provs.framework.core.platforms.SHELL +import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall +import org.domaindrivenarchitecture.provs.framework.ubuntu.user.base.makeCurrentUserSudoerWithoutPasswordRequired import org.domaindrivenarchitecture.provs.test.tags.ContainerTest +import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest import org.domaindrivenarchitecture.provs.test.testDockerWithSudo import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue val DEFAULT_START_MODE_TEST_CONTAINER = ContainerStartMode.USE_RUNNING_ELSE_CREATE @@ -22,4 +27,42 @@ class ContainerUbuntuHostProcessorTest { assertEquals(0, res.exitCode) assertEquals("abc", res.out) } + + + @ExtensiveContainerTest + fun test_reopeing_ssh_session_succeeds() { + + // given + val containerName = "prov-test-ssh-with-container" + val password = Secret("testuserpw") + + val prov = Prov.newInstance( + ContainerUbuntuHostProcessor( + containerName, + startMode = ContainerStartMode.USE_RUNNING_ELSE_CREATE, + sudo = true, + dockerImage = "ubuntu_plus_user", + options = "--expose=22" + ), + progressType = ProgressType.NONE + ) + prov.task { + makeCurrentUserSudoerWithoutPasswordRequired(password) + aptInstall("openssh-server") + cmd("sudo service ssh start") + } + + val ipOfContainer = local().cmd("sudo docker inspect -f \"{{ .NetworkSettings.IPAddress }}\" $containerName").out?.trim() + ?: throw IllegalStateException("Ip not found") + val remoteProvBySsh = remote(ipOfContainer, "testuser", password) + + // when + val firstSessionResult = remoteProvBySsh.cmd("echo 1") + val secondSessionResult = remoteProvBySsh.cmd("echo 1") + + // then + assertTrue(firstSessionResult.success) + assertTrue(secondSessionResult.success) + } + } \ No newline at end of file