refactor cli parse and add cli command for k3d
This commit is contained in:
parent
5b15467cc2
commit
9dd8f55de8
9 changed files with 250 additions and 89 deletions
|
@ -41,6 +41,10 @@ test {
|
||||||
}
|
}
|
||||||
|
|
||||||
useJUnitPlatform {
|
useJUnitPlatform {
|
||||||
|
def excludedTags = System.getProperty("excludeTags")
|
||||||
|
if (System.getProperty("excludeTags") != null) {
|
||||||
|
excludeTags(excludedTags)
|
||||||
|
}
|
||||||
if (System.getenv("CI_JOB_TOKEN") != null) {
|
if (System.getenv("CI_JOB_TOKEN") != null) {
|
||||||
excludeTags('containernonci')
|
excludeTags('containernonci')
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package org.domaindrivenarchitecture.provs.core.cli
|
package org.domaindrivenarchitecture.provs.core.cli
|
||||||
|
|
||||||
import kotlinx.cli.ArgParser
|
|
||||||
import kotlinx.cli.ArgType
|
|
||||||
import kotlinx.cli.default
|
|
||||||
import org.domaindrivenarchitecture.provs.core.Prov
|
import org.domaindrivenarchitecture.provs.core.Prov
|
||||||
import org.domaindrivenarchitecture.provs.core.Secret
|
import org.domaindrivenarchitecture.provs.core.Secret
|
||||||
import org.domaindrivenarchitecture.provs.core.local
|
import org.domaindrivenarchitecture.provs.core.local
|
||||||
|
@ -15,85 +12,31 @@ import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
class CliCommand(
|
/**
|
||||||
val localHost: Boolean?,
|
* Returns a Prov instance according to the targetCommand.
|
||||||
val remoteHost: String?,
|
* E.g. it returns a local Prov instance if targetCommand.isValidLocalhost() is true or
|
||||||
val userName: String?,
|
* returns a remote Prov instance if targetCommand.isValidRemote() is true.
|
||||||
val sshWithPasswordPrompt: Boolean,
|
*
|
||||||
val sshWithGopassPath: String?,
|
* If the target is remote and if parameter remoteHostSetSudoWithoutPasswordRequired is set to true,
|
||||||
val sshWithKey: Boolean
|
* it will enable sudo without password on the remote machine (in case this was not yet enabled).
|
||||||
) {
|
*/
|
||||||
fun isValidLocalhost(): Boolean {
|
|
||||||
return (localHost ?: false) && remoteHost == null && userName == null && sshWithGopassPath == null &&
|
|
||||||
!sshWithPasswordPrompt && !sshWithKey
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasValidPasswordOption(): Boolean {
|
|
||||||
return (sshWithGopassPath != null) xor sshWithPasswordPrompt xor sshWithKey
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isValidRemote(): Boolean {
|
|
||||||
return remoteHost != null && userName != null && hasValidPasswordOption()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isValid(): Boolean {
|
|
||||||
return (isValidLocalhost() || isValidRemote())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseCli(
|
|
||||||
programName: String = "java -jar provs.jar",
|
|
||||||
args: Array<String>
|
|
||||||
): CliCommand {
|
|
||||||
val parser = ArgParser(programName)
|
|
||||||
|
|
||||||
val remoteHost by parser.option(
|
|
||||||
ArgType.String, shortName =
|
|
||||||
"r", description = "provision to remote host - either localHost or remoteHost must be specified"
|
|
||||||
)
|
|
||||||
val localHost by parser.option(
|
|
||||||
ArgType.Boolean, shortName =
|
|
||||||
"l", description = "provision to local machine - either localHost or remoteHost must be specified"
|
|
||||||
)
|
|
||||||
val userName by parser.option(
|
|
||||||
ArgType.String,
|
|
||||||
shortName = "u",
|
|
||||||
description = "user for remote provisioning."
|
|
||||||
)
|
|
||||||
val sshWithGopassPath by parser.option(
|
|
||||||
ArgType.String,
|
|
||||||
shortName = "p",
|
|
||||||
description = "password stored at gopass path"
|
|
||||||
)
|
|
||||||
val sshWithPasswordPrompt by parser.option(
|
|
||||||
ArgType.Boolean,
|
|
||||||
shortName = "i",
|
|
||||||
description = "prompt for password interactive"
|
|
||||||
).default(false)
|
|
||||||
val sshWithKey by parser.option(
|
|
||||||
ArgType.Boolean,
|
|
||||||
shortName = "k",
|
|
||||||
description = "provision over ssh using user & ssh key"
|
|
||||||
).default(false)
|
|
||||||
parser.parse(args)
|
|
||||||
|
|
||||||
return CliCommand(
|
|
||||||
localHost, remoteHost, userName, sshWithPasswordPrompt, sshWithGopassPath, sshWithKey
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal fun createProvInstance(
|
internal fun createProvInstance(
|
||||||
cliCommand: CliCommand,
|
targetCommand: TargetCliCommand,
|
||||||
remoteHostSetSudoWithoutPasswordRequired: Boolean = false
|
remoteHostSetSudoWithoutPasswordRequired: Boolean = false
|
||||||
): Prov {
|
): Prov {
|
||||||
if (cliCommand.isValid()) {
|
if (targetCommand.isValid()) {
|
||||||
val password: Secret? = if (cliCommand.isValidRemote()) retrievePassword(cliCommand) else null
|
val password: Secret? = if (targetCommand.isValidRemote()) retrievePassword(targetCommand) else null
|
||||||
|
|
||||||
if (cliCommand.isValidLocalhost()) {
|
if (targetCommand.isValidLocalhost()) {
|
||||||
return local()
|
return local()
|
||||||
} else if (cliCommand.isValidRemote()) {
|
} else if (targetCommand.isValidRemote()) {
|
||||||
return createProvInstanceRemote(cliCommand.remoteHost!!, cliCommand.userName!!, cliCommand.sshWithKey, password, remoteHostSetSudoWithoutPasswordRequired)
|
return createProvInstanceRemote(
|
||||||
|
targetCommand.remoteHost!!,
|
||||||
|
targetCommand.userName!!,
|
||||||
|
targetCommand.sshWithKey,
|
||||||
|
password,
|
||||||
|
remoteHostSetSudoWithoutPasswordRequired
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
throw IllegalArgumentException("Error: neither a valid localHost nor a valid remoteHost was specified! Use option -h for help.")
|
throw IllegalArgumentException("Error: neither a valid localHost nor a valid remoteHost was specified! Use option -h for help.")
|
||||||
}
|
}
|
||||||
|
@ -134,7 +77,7 @@ private fun createProvInstanceRemote(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun retrievePassword(cliCommand: CliCommand): Secret? {
|
internal fun retrievePassword(cliCommand: TargetCliCommand): Secret? {
|
||||||
var password: Secret? = null
|
var password: Secret? = null
|
||||||
if (cliCommand.isValidRemote()) {
|
if (cliCommand.isValidRemote()) {
|
||||||
if (cliCommand.sshWithPasswordPrompt) {
|
if (cliCommand.sshWithPasswordPrompt) {
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.core.cli
|
||||||
|
|
||||||
|
import org.domaindrivenarchitecture.provs.core.Prov
|
||||||
|
import org.domaindrivenarchitecture.provs.core.Secret
|
||||||
|
import org.domaindrivenarchitecture.provs.core.local
|
||||||
|
import org.domaindrivenarchitecture.provs.core.remote
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.GopassSecretSource
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.PromptSecretSource
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.currentUserCanSudo
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.makeUserSudoerWithNoSudoPasswordRequired
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
|
class TargetCliCommand(
|
||||||
|
val localHost: Boolean?,
|
||||||
|
val remoteHost: String?,
|
||||||
|
val userName: String?,
|
||||||
|
val sshWithPasswordPrompt: Boolean,
|
||||||
|
val sshWithGopassPath: String?,
|
||||||
|
val sshWithKey: Boolean
|
||||||
|
) {
|
||||||
|
fun isValidLocalhost(): Boolean {
|
||||||
|
return (localHost ?: false) && remoteHost == null && userName == null && sshWithGopassPath == null &&
|
||||||
|
!sshWithPasswordPrompt && !sshWithKey
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasValidPasswordOption(): Boolean {
|
||||||
|
return (sshWithGopassPath != null) xor sshWithPasswordPrompt xor sshWithKey
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValidRemote(): Boolean {
|
||||||
|
return remoteHost != null && userName != null && hasValidPasswordOption()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValid(): Boolean {
|
||||||
|
return (isValidLocalhost() || isValidRemote())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseTarget(
|
||||||
|
programName: String = "java -jar provs.jar",
|
||||||
|
args: Array<String>
|
||||||
|
): TargetCliCommand {
|
||||||
|
val parser = TargetParser(programName)
|
||||||
|
parser.parse(args)
|
||||||
|
|
||||||
|
return TargetCliCommand(
|
||||||
|
parser.localHost,
|
||||||
|
parser.remoteHost,
|
||||||
|
parser.userName,
|
||||||
|
parser.sshWithPasswordPrompt,
|
||||||
|
parser.sshWithGopassPath,
|
||||||
|
parser.sshWithKey
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.core.cli
|
||||||
|
|
||||||
|
import kotlinx.cli.ArgParser
|
||||||
|
import kotlinx.cli.ArgType
|
||||||
|
import kotlinx.cli.default
|
||||||
|
import org.domaindrivenarchitecture.provs.core.Prov
|
||||||
|
import org.domaindrivenarchitecture.provs.core.Secret
|
||||||
|
import org.domaindrivenarchitecture.provs.core.local
|
||||||
|
import org.domaindrivenarchitecture.provs.core.remote
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.GopassSecretSource
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.secret.secretSources.PromptSecretSource
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.currentUserCanSudo
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.makeUserSudoerWithNoSudoPasswordRequired
|
||||||
|
import org.domaindrivenarchitecture.provs.ubuntu.user.base.whoami
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
open class TargetParser(name: String) : ArgParser(name) {
|
||||||
|
val remoteHost by option(
|
||||||
|
ArgType.String, shortName =
|
||||||
|
"r", description = "provision to remote host - either localHost or remoteHost must be specified"
|
||||||
|
)
|
||||||
|
val localHost by option(
|
||||||
|
ArgType.Boolean, shortName =
|
||||||
|
"l", description = "provision to local machine - either localHost or remoteHost must be specified"
|
||||||
|
)
|
||||||
|
val userName by option(
|
||||||
|
ArgType.String,
|
||||||
|
shortName = "u",
|
||||||
|
description = "user for remote provisioning."
|
||||||
|
)
|
||||||
|
val sshWithGopassPath by option(
|
||||||
|
ArgType.String,
|
||||||
|
shortName = "p",
|
||||||
|
description = "password stored at gopass path"
|
||||||
|
)
|
||||||
|
val sshWithPasswordPrompt by option(
|
||||||
|
ArgType.Boolean,
|
||||||
|
shortName = "i",
|
||||||
|
description = "prompt for password interactive"
|
||||||
|
).default(false)
|
||||||
|
val sshWithKey by option(
|
||||||
|
ArgType.Boolean,
|
||||||
|
shortName = "k",
|
||||||
|
description = "provision over ssh using user & ssh key"
|
||||||
|
).default(false)
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.application
|
package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.application
|
||||||
|
|
||||||
import org.domaindrivenarchitecture.provs.core.cli.createProvInstance
|
import org.domaindrivenarchitecture.provs.core.cli.createProvInstance
|
||||||
import org.domaindrivenarchitecture.provs.core.cli.parseCli
|
import org.domaindrivenarchitecture.provs.extensions.server_software.k3s.domain.installK3sAsContainers
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,8 +11,16 @@ import org.domaindrivenarchitecture.provs.core.cli.parseCli
|
||||||
* Get help with option -h
|
* Get help with option -h
|
||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val cmd = parseCli("java -jar provs-server.jar", args)
|
|
||||||
val prov = createProvInstance(cmd)
|
|
||||||
|
|
||||||
prov.provisionK3s()
|
val cmd = parseServerArguments("java -jar provs-server.jar", args)
|
||||||
|
if (!cmd.isValid()) {
|
||||||
|
println("Arguments are not valid, pls try -h for help.")
|
||||||
|
exitProcess(1)
|
||||||
|
}
|
||||||
|
val prov = createProvInstance(cmd.target)
|
||||||
|
|
||||||
|
when (cmd.type()) {
|
||||||
|
CliK3sArgumentsParser.K3sType.K3S -> prov.provisionK3s()
|
||||||
|
CliK3sArgumentsParser.K3sType.K3D -> prov.installK3sAsContainers()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.application
|
||||||
|
|
||||||
|
import kotlinx.cli.ArgType
|
||||||
|
import kotlinx.cli.default
|
||||||
|
import org.domaindrivenarchitecture.provs.core.cli.TargetParser
|
||||||
|
|
||||||
|
class CliK3sArgumentsParser(name: String) : TargetParser(name) {
|
||||||
|
|
||||||
|
enum class K3sType() {
|
||||||
|
K3S, K3D
|
||||||
|
}
|
||||||
|
|
||||||
|
val type by option(
|
||||||
|
ArgType.String,
|
||||||
|
"type",
|
||||||
|
"t",
|
||||||
|
"either k3s (for standalone) or k3d for k3s running in a container"
|
||||||
|
).default("k3s")
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.application
|
||||||
|
|
||||||
|
import org.domaindrivenarchitecture.provs.core.cli.TargetCliCommand
|
||||||
|
|
||||||
|
|
||||||
|
class ServerCliCommand(private val k3sType: String, val target: TargetCliCommand) {
|
||||||
|
fun isValid(): Boolean {
|
||||||
|
return target.isValid() && hasValidK3sType()
|
||||||
|
}
|
||||||
|
fun hasValidK3sType(): Boolean {
|
||||||
|
return CliK3sArgumentsParser.K3sType.values().map { it.name }.contains(k3sType.uppercase())
|
||||||
|
}
|
||||||
|
fun type() = CliK3sArgumentsParser.K3sType.valueOf(k3sType.uppercase())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseServerArguments(
|
||||||
|
programName: String = "java -jar provs.jar",
|
||||||
|
args: Array<String>
|
||||||
|
): ServerCliCommand {
|
||||||
|
val parser = CliK3sArgumentsParser(programName)
|
||||||
|
parser.parse(args)
|
||||||
|
|
||||||
|
return ServerCliCommand(
|
||||||
|
parser.type,
|
||||||
|
TargetCliCommand(
|
||||||
|
parser.localHost,
|
||||||
|
parser.remoteHost,
|
||||||
|
parser.userName,
|
||||||
|
parser.sshWithPasswordPrompt,
|
||||||
|
parser.sshWithGopassPath,
|
||||||
|
parser.sshWithKey
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ package org.domaindrivenarchitecture.provs.core.cli
|
||||||
import org.junit.jupiter.api.Assertions.*
|
import org.junit.jupiter.api.Assertions.*
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
internal class CliCommandTest {
|
internal class TargetCliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_localhost_with_default() {
|
fun parse_localhost_with_default() {
|
||||||
val parseCli = parseCli(args = emptyArray())
|
val parseCli = parseTarget(args = emptyArray())
|
||||||
|
|
||||||
assertFalse(parseCli.isValidLocalhost())
|
assertFalse(parseCli.isValidLocalhost())
|
||||||
assertFalse(parseCli.isValidRemote())
|
assertFalse(parseCli.isValidRemote())
|
||||||
|
@ -16,7 +16,7 @@ internal class CliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_localhost() {
|
fun parse_localhost() {
|
||||||
val parseCli = parseCli(args = arrayOf("-l"))
|
val parseCli = parseTarget(args = arrayOf("-l"))
|
||||||
assertTrue(parseCli.isValidLocalhost())
|
assertTrue(parseCli.isValidLocalhost())
|
||||||
assertFalse(parseCli.isValidRemote())
|
assertFalse(parseCli.isValidRemote())
|
||||||
assertTrue(parseCli.isValid())
|
assertTrue(parseCli.isValid())
|
||||||
|
@ -24,7 +24,7 @@ internal class CliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_remote_with_missing_passwordoption() {
|
fun parse_remote_with_missing_passwordoption() {
|
||||||
val parseCli = parseCli(args = arrayOf("-r", "1.2.3.4", "-u", "user"))
|
val parseCli = parseTarget(args = arrayOf("-r", "1.2.3.4", "-u", "user"))
|
||||||
|
|
||||||
assertFalse(parseCli.isValidLocalhost())
|
assertFalse(parseCli.isValidLocalhost())
|
||||||
assertEquals("1.2.3.4", parseCli.remoteHost)
|
assertEquals("1.2.3.4", parseCli.remoteHost)
|
||||||
|
@ -35,7 +35,7 @@ internal class CliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_remote_with_remote_key() {
|
fun parse_remote_with_remote_key() {
|
||||||
val parseCli = parseCli(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-k"))
|
val parseCli = parseTarget(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-k"))
|
||||||
|
|
||||||
assertFalse(parseCli.isValidLocalhost())
|
assertFalse(parseCli.isValidLocalhost())
|
||||||
assertEquals("1.2.3.4", parseCli.remoteHost)
|
assertEquals("1.2.3.4", parseCli.remoteHost)
|
||||||
|
@ -45,7 +45,7 @@ internal class CliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_remote_with_remote_password_prompt() {
|
fun parse_remote_with_remote_password_prompt() {
|
||||||
val parseCli = parseCli(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-i"))
|
val parseCli = parseTarget(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-i"))
|
||||||
|
|
||||||
assertEquals("1.2.3.4", parseCli.remoteHost)
|
assertEquals("1.2.3.4", parseCli.remoteHost)
|
||||||
assertEquals("user", parseCli.userName)
|
assertEquals("user", parseCli.userName)
|
||||||
|
@ -54,7 +54,7 @@ internal class CliCommandTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parse_remote_with_remote_password_gopass_path() {
|
fun parse_remote_with_remote_password_gopass_path() {
|
||||||
val parseCli = parseCli(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-p", "gopass/path"))
|
val parseCli = parseTarget(args = arrayOf("-r", "1.2.3.4", "-u", "user", "-p", "gopass/path"))
|
||||||
|
|
||||||
assertEquals("1.2.3.4", parseCli.remoteHost)
|
assertEquals("1.2.3.4", parseCli.remoteHost)
|
||||||
assertEquals("user", parseCli.userName)
|
assertEquals("user", parseCli.userName)
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.domaindrivenarchitecture.provs.extensions.server_software.k3s.application
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
|
||||||
|
internal class CliK3sCommandKtTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_parseServerArguments_are_valid_for_k3s() {
|
||||||
|
// when
|
||||||
|
val cmd = parseServerArguments(args = arrayOf("-l", "-t", "k3s"))
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(cmd.isValid())
|
||||||
|
assertEquals(CliK3sArgumentsParser.K3sType.K3S, cmd.type())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_parseServerArguments_are_invalid_without_target() {
|
||||||
|
// when
|
||||||
|
val cmd = parseServerArguments(args = arrayOf("-t", "k3s"))
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertFalse(cmd.isValid())
|
||||||
|
assertEquals(CliK3sArgumentsParser.K3sType.K3S, cmd.type())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_parseServerArguments_has_default_type_k3s() {
|
||||||
|
// when
|
||||||
|
val cmd = parseServerArguments(args = arrayOf("-l"))
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(cmd.isValid())
|
||||||
|
assertEquals(CliK3sArgumentsParser.K3sType.K3S, cmd.type())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_parseServerArguments_are_valid_for_k3d() {
|
||||||
|
// when
|
||||||
|
val cmd = parseServerArguments(args = arrayOf("-l", "-t", "k3d"))
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertTrue(cmd.isValid())
|
||||||
|
assertEquals(CliK3sArgumentsParser.K3sType.K3D, cmd.type())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue