Skip to content

Commit 1dece08

Browse files
committed
Encapsulate version in checks in features object
1 parent fecbe98 commit 1dece08

File tree

2 files changed

+60
-17
lines changed

2 files changed

+60
-17
lines changed

src/main/kotlin/com/coder/gateway/cli/CoderCLIManager.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ fun ensureCLI(
9696
return if (cliMatches == null && dataCLIMatches != null) dataCLI else cli
9797
}
9898

99+
/**
100+
* The supported features of the CLI.
101+
*/
102+
data class Features (
103+
val disableAutostart: Boolean = false,
104+
)
105+
99106
/**
100107
* Manage the CLI for a single deployment.
101108
*/
@@ -200,10 +207,10 @@ class CoderCLIManager(
200207
/**
201208
* Configure SSH to use this binary.
202209
*
203-
* This can take a version for testing purposes only.
210+
* This can take supported features for testing purposes only.
204211
*/
205-
fun configSsh(workspaceNames: List<String>, version: SemVer? = tryVersion()) {
206-
writeSSHConfig(modifySSHConfig(readSSHConfig(), workspaceNames, version))
212+
fun configSsh(workspaceNames: List<String>, feats: Features = features) {
213+
writeSSHConfig(modifySSHConfig(readSSHConfig(), workspaceNames, feats))
207214
}
208215

209216
/**
@@ -221,8 +228,11 @@ class CoderCLIManager(
221228
* Given an existing SSH config modify it to add or remove the config for
222229
* this deployment and return the modified config or null if it does not
223230
* need to be modified.
231+
*
232+
* If features are not provided, calculate them based on the binary
233+
* version.
224234
*/
225-
private fun modifySSHConfig(contents: String?, workspaceNames: List<String>, version: SemVer?): String? {
235+
private fun modifySSHConfig(contents: String?, workspaceNames: List<String>, feats: Features): String? {
226236
val host = deploymentURL.safeHost()
227237
val startBlock = "# --- START CODER JETBRAINS $host"
228238
val endBlock = "# --- END CODER JETBRAINS $host"
@@ -233,8 +243,7 @@ class CoderCLIManager(
233243
if (settings.headerCommand.isNotBlank()) "--header-command" else null,
234244
if (settings.headerCommand.isNotBlank()) escapeSubcommand(settings.headerCommand) else null,
235245
"ssh", "--stdio",
236-
// Autostart on SSH was added in 2.5.0.
237-
if (settings.disableAutostart && version != null && version >= SemVer(2, 5, 0)) "--disable-autostart" else null)
246+
if (settings.disableAutostart && feats.disableAutostart) "--disable-autostart" else null)
238247
val blockContent = workspaceNames.joinToString(
239248
System.lineSeparator(),
240249
startBlock + System.lineSeparator(),
@@ -392,6 +401,18 @@ class CoderCLIManager(
392401
return stdout
393402
}
394403

404+
val features: Features
405+
get() {
406+
val version = tryVersion()
407+
return if (version == null) {
408+
Features()
409+
} else {
410+
Features(
411+
// Autostart with SSH was added in 2.5.0.
412+
disableAutostart = version >= SemVer(2, 5, 0))
413+
}
414+
}
415+
395416
companion object {
396417
val logger = Logger.getInstance(CoderCLIManager::class.java.simpleName)
397418

src/test/kotlin/com/coder/gateway/cli/CoderCLIManagerTest.kt

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,18 @@ import kotlin.test.assertTrue
3333

3434
internal class CoderCLIManagerTest {
3535
private fun mkbin(version: String): String {
36-
return listOf("#!/bin/sh", """echo '{"version": "${version}"}'""")
36+
return listOf("#!/bin/sh", """echo '{"version": "$version"}'""")
3737
.joinToString("\n")
3838
}
3939

40-
private fun mockServer(errorCode: Int = 0): Pair<HttpServer, URL> {
40+
private fun mockServer(errorCode: Int = 0, version: String? = null): Pair<HttpServer, URL> {
4141
val srv = HttpServer.create(InetSocketAddress(0), 0)
4242
srv.createContext("/") {exchange ->
4343
var code = HttpURLConnection.HTTP_OK
4444
// TODO: Is there some simple way to create an executable file on
4545
// Windows without having to execute something to generate said
4646
// executable or having to commit one to the repo?
47-
var response = mkbin("${srv.address.port}.0.0")
47+
var response = mkbin(version ?: "${srv.address.port}.0.0")
4848
val eTags = exchange.requestHeaders["If-None-Match"]
4949
if (exchange.requestURI.path == "/bin/override") {
5050
code = HttpURLConnection.HTTP_OK
@@ -241,7 +241,7 @@ internal class CoderCLIManagerTest {
241241
val remove: String,
242242
val headerCommand: String?,
243243
val disableAutostart: Boolean = false,
244-
val version: SemVer? = null,
244+
val features: Features? = null,
245245
)
246246

247247
@Test
@@ -265,11 +265,8 @@ internal class CoderCLIManagerTest {
265265
} else {
266266
SSHTest(listOf("header"), null, "header-command", "blank", "my-header-command --url=\"\$CODER_URL\" --test=\"foo bar\" --literal='\$CODER_URL'")
267267
},
268-
SSHTest(listOf("foo"), null, "disable-autostart", "blank", null, true, SemVer(2, 5, 0)),
269-
SSHTest(listOf("foo"), null, "disable-autostart", "blank", null, true, SemVer(3, 5, 0)),
270-
SSHTest(listOf("foo"), null, "no-disable-autostart", "blank", null, true, SemVer(2, 4, 9)),
271-
SSHTest(listOf("foo"), null, "no-disable-autostart", "blank", null, true, SemVer(1, 0, 1)),
272-
SSHTest(listOf("foo"), null, "no-disable-autostart", "blank", null, true),
268+
SSHTest(listOf("foo"), null, "disable-autostart", "blank", null, true, Features(true)),
269+
SSHTest(listOf("foo"), null, "no-disable-autostart", "blank", null, true, Features(false)),
273270
)
274271

275272
val newlineRe = "\r?\n".toRegex()
@@ -299,12 +296,12 @@ internal class CoderCLIManagerTest {
299296
.replace("/tmp/coder-gateway/test.coder.invalid/coder-linux-amd64", escape(ccm.localBinaryPath.toString()))
300297

301298
// Add workspaces.
302-
ccm.configSsh(it.workspaces, it.version)
299+
ccm.configSsh(it.workspaces, it.features ?: Features())
303300

304301
assertEquals(expectedConf, settings.sshConfigPath.toFile().readText())
305302

306303
// Remove configuration.
307-
ccm.configSsh(emptyList(), it.version)
304+
ccm.configSsh(emptyList(), it.features ?: Features())
308305

309306
// Remove is the configuration we expect after removing.
310307
assertEquals(
@@ -554,6 +551,31 @@ internal class CoderCLIManagerTest {
554551
srv.stop(0)
555552
}
556553

554+
@Test
555+
fun testFeatures() {
556+
if (getOS() == OS.WINDOWS) {
557+
return // Cannot execute mock binaries on Windows.
558+
}
559+
560+
val tests = listOf(
561+
Pair("2.5.0", Features(true)),
562+
Pair("4.9.0", Features(true)),
563+
Pair("2.4.9", Features(false)),
564+
Pair("1.0.1", Features(false)),
565+
)
566+
567+
tests.forEach {
568+
val (srv, url) = mockServer(version = it.first)
569+
val ccm = CoderCLIManager(url, CoderSettings(CoderSettingsState(
570+
dataDirectory = tmpdir.resolve("features").toString()))
571+
)
572+
assertEquals(true, ccm.download())
573+
assertEquals(it.second, ccm.features, "version: ${it.first}")
574+
575+
srv.stop(0)
576+
}
577+
}
578+
557579
companion object {
558580
private val tmpdir: Path = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test/cli-manager")
559581

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy