diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Utils.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Utils.kt index 97340dd..3b4f1cb 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Utils.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/core/Utils.kt @@ -53,7 +53,7 @@ fun String.escapeDollar(): String = replace("$", "\\$") fun String.escapeSingleQuoteForShell(): String = replace("'", "'\"'\"'") fun String.escapeProcentForPrintf(): String = replace("%", "%%") fun String.endingWithFileSeparator(): String = if (isNotEmpty() && (last() != fileSeparatorChar())) this + fileSeparator() else this - +fun prefixWithSudo(text: String, sudo: Boolean): String = if (sudo) "sudo $text" else text // -------------- Functions for system related properties ----------------- fun fileSeparator(): String = File.separator diff --git a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/Filesystem.kt b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/Filesystem.kt index 8ac3f28..3ac5d96 100644 --- a/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/Filesystem.kt +++ b/src/main/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/Filesystem.kt @@ -10,7 +10,7 @@ import java.io.File * Returns true if the given file exists. */ fun Prov.fileExists(file: String, sudo: Boolean = false): Boolean { - return cmdNoEval((if (sudo) "sudo " else "") + "test -e " + file).success + return cmdNoEval(prefixWithSudo("test -e " + file, sudo)).success } @@ -116,28 +116,32 @@ fun Prov.createSecretFile( fullyQualifiedFilename: String, secret: Secret, posixFilePermission: String? = null -): ProvResult = - def { - posixFilePermission?.let { - ensureValidPosixFilePermission(posixFilePermission) - cmd("install -m $posixFilePermission /dev/null $fullyQualifiedFilename") - } - cmdNoLog("echo '" + secret.plain().escapeSingleQuote() + "' > $fullyQualifiedFilename") +): ProvResult = def { + posixFilePermission?.let { + ensureValidPosixFilePermission(posixFilePermission) + cmd("install -m $posixFilePermission /dev/null $fullyQualifiedFilename") } + cmdNoLog("echo '" + secret.plain().escapeSingleQuote() + "' > $fullyQualifiedFilename") +} fun Prov.deleteFile(file: String, path: String? = null, sudo: Boolean = false): ProvResult = def { - cmd((path?.let { "cd $path && " } ?: "") + (if (sudo) "sudo " else "") + "rm $file") + val fullyQualifiedFilename = (path?.normalizePath() ?: "") + file + if (fileExists(fullyQualifiedFilename, sudo = sudo)) { + cmd(prefixWithSudo("rm $fullyQualifiedFilename", sudo)) + } else { + ProvResult(true, "File to be deleted did not exist.") + } } fun Prov.fileContainsText(file: String, content: String, sudo: Boolean = false): Boolean { - return cmdNoEval((if (sudo) "sudo " else "") + "grep -- '${content.escapeSingleQuote()}' $file").success + return cmdNoEval(prefixWithSudo( "grep -- '${content.escapeSingleQuote()}' $file", sudo)).success } fun Prov.fileContent(file: String, sudo: Boolean = false): String? { - return cmd((if (sudo) "sudo " else "") + "cat $file").out + return cmd(prefixWithSudo("cat $file", sudo)).out } @@ -283,10 +287,23 @@ fun Prov.fileSize(filename: String): Int? { private fun ensureValidPosixFilePermission(posixFilePermission: String) { - if (!Regex("^[0-7]{3}$").matches(posixFilePermission)) throw RuntimeException("Wrong file permission ($posixFilePermission), permission must consist of 3 digits as e.g. 664 ") + if (!Regex("^[0-7]{3}$").matches(posixFilePermission)) throw IllegalArgumentException("Wrong file permission ($posixFilePermission), permission must consist of 3 digits as e.g. 664") } +/** + * Returns a command encapsulated in a shell command and executed with sudo. + * For simple cases consider sudo as prefix instead. + * @see prefixWithSudo + */ private fun String.sudoizeCommand(): String { return "sudo " + SHELL + " -c " + this.escapeAndEncloseByDoubleQuoteForShell() +} + + +/** + * Returns path with a trailing fileSeparator if path not empty + */ +private fun String.normalizePath(): String { + return if (this == "" || this.endsWith(fileSeparatorChar())) this else this + fileSeparator() } \ No newline at end of file diff --git a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/FilesystemKtTest.kt b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/FilesystemKtTest.kt index d5730eb..3772894 100644 --- a/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/FilesystemKtTest.kt +++ b/src/test/kotlin/org/domaindrivenarchitecture/provs/framework/ubuntu/filesystem/base/FilesystemKtTest.kt @@ -70,7 +70,7 @@ internal class FilesystemKtTest { @Test @ContainerTest - fun checkingCreatingDeletingFile() { + fun create_and_delete_file() { // given val prov = defaultTestContainer() @@ -82,6 +82,7 @@ internal class FilesystemKtTest { val res4b = prov.fileContainsText("testfile", "some non-existing content") val res5 = prov.deleteFile("testfile") val res6 = prov.fileExists("testfile") + val res7 = prov.deleteFile("testfile") // idem-potent // then assertFalse(res1) @@ -91,12 +92,13 @@ internal class FilesystemKtTest { assertFalse(res4b) assertTrue(res5.success) assertFalse(res6) + assertTrue(res7.success) } @Test @ContainerTest - fun checkingCreatingDeletingFileWithSudo() { + fun create_and_delete_file_with_sudo() { // given val prov = defaultTestContainer() @@ -111,6 +113,7 @@ internal class FilesystemKtTest { val res6 = prov.fileExists(file) val res7 = prov.deleteFile(file, sudo = true) val res8 = prov.fileExists(file) + val res9 = prov.deleteFile(file, sudo = true) // check idem-potence // then assertFalse(res1) @@ -122,12 +125,13 @@ internal class FilesystemKtTest { assertTrue(res6) assertTrue(res7.success) assertFalse(res8) + assertTrue(res9.success) } @Test @ContainerTest - fun checkingCreatingDeletingDir() { + fun create_and_delete_dir() { // given val prov = defaultTestContainer() @@ -157,7 +161,7 @@ internal class FilesystemKtTest { @Test @ContainerTest - fun checkingCreatingDeletingDirWithSudo() { + fun create_and_delete_dir_with_sudo() { // given val prov = defaultTestContainer()