From eefc6bd3e8591f0f23b7736ce674ec318991872f Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Tue, 22 Sep 2020 22:27:06 +0200 Subject: [PATCH 1/5] Hosts editing works on Mac --- build.gradle.kts | 5 ++ hosts/build.gradle.kts | 30 +++++++++ hosts/src/main/kotlin/main.kt | 61 +++++++++++++++++++ settings.gradle.kts | 2 + .../environment/tasks/EnvironmentHosts.kt | 32 +++++++++- 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 hosts/build.gradle.kts create mode 100644 hosts/src/main/kotlin/main.kt diff --git a/build.gradle.kts b/build.gradle.kts index 1bae4d3..4537e4b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -56,6 +56,11 @@ val check by tasks.getting(Task::class) { } tasks { + jar { + dependsOn(":hosts:jar") + from(provider { project(":hosts").tasks.getByName("jar") }) + } + register("sourcesJar") { archiveClassifier.set("sources") dependsOn("classes") diff --git a/hosts/build.gradle.kts b/hosts/build.gradle.kts new file mode 100644 index 0000000..f667757 --- /dev/null +++ b/hosts/build.gradle.kts @@ -0,0 +1,30 @@ +plugins { + kotlin("jvm") + application + java +} + +description = "Hosts Editor" +version = "" + +repositories { + jcenter() +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") +} + +application { + mainClass.set("MainKt") +} + +tasks { + jar { + manifest { + attributes["Implementation-Title"] = project.description + attributes["Main-Class"] = "MainKt" + } + from(configurations.runtimeClasspath.get().files.map { if (it.isDirectory) it else zipTree(it) }) + } +} diff --git a/hosts/src/main/kotlin/main.kt b/hosts/src/main/kotlin/main.kt new file mode 100644 index 0000000..1c89489 --- /dev/null +++ b/hosts/src/main/kotlin/main.kt @@ -0,0 +1,61 @@ +import java.io.File + +fun main(args: Array) { + val sourceName = args.getOrNull(0) ?: "mysite" + val sourceFile = File(args.getOrNull(1) ?: ".gradle/environment/hosts.txt") + val sourceSection = Section(sourceName, sourceFile.readText().lines().map { it.trim() }) + val targetFile = File(args.getOrNull(2) ?: "/etc/hosts") + + val text = targetFile.readText() + val sections = Section.parseAll(text) + + val targetSection = sections.find { it.name == sourceSection.name } + if (targetSection != null) { + targetFile.writeText(text.replace(targetSection.render(), sourceSection.render())) + } else { + targetFile.appendText("${System.lineSeparator()}${sourceSection.render()}") + } +} + +data class Section(val name: String, val entries: List) { + fun render() = mutableListOf().apply { + add("#environment-start") + add("#name=$name") + addAll(entries) + add("#environment-end") + }.joinToString(System.lineSeparator()) + + companion object { + fun parseAll(text: String): List
{ + val sections = mutableListOf
() + + var section = false + var sectionName = "" + val sectionLines = mutableListOf() + + text.lineSequence().forEach { line -> + when (val l = line.trim()) { + "#environment-start" -> { + section = true + } + "#environment-end" -> { + sections.add(Section(sectionName, sectionLines.toList())) + section = false + sectionLines.clear() + } + else -> { + if (section) { + if (l.startsWith("#name=")) { + sectionName = l.substringAfter("#name=") + } else { + sectionLines.add(l) + } + } + } + } + } + + return sections + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 52ab668..4e33f3e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1,3 @@ rootProject.name = "environment-plugin" + +include(":hosts") \ No newline at end of file diff --git a/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt b/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt index 0ad3191..450b2f7 100644 --- a/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt +++ b/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt @@ -1,14 +1,42 @@ package com.cognifide.gradle.environment.tasks import com.cognifide.gradle.environment.EnvironmentDefaultTask +import org.buildobjects.process.ProcBuilder import org.gradle.api.tasks.TaskAction +import org.gradle.internal.os.OperatingSystem open class EnvironmentHosts : EnvironmentDefaultTask() { @TaskAction fun appendHosts() { - logger.lifecycle("Hosts entries to be appended to ${environment.hosts.osFile.get()}:") - logger.quiet(environment.hosts.appendix) + val tmpFile = environment.rootDir.get().asFile.resolve("hosts.txt").apply { + writeText(environment.hosts.appendix) + } + val osFile = environment.hosts.osFile.get() + + val sectionName = environment.docker.stack.internalName + val editorFile = environment.rootDir.get().asFile.resolve("hosts.jar") + + if (OperatingSystem.current().isWindows) { + val scriptFile = environment.rootDir.get().asFile.resolve("hosts.bat") + scriptFile.writeText(""" + powershell -command "Start-Process cmd -ArgumentList '/C cd %CD% && java -jar $editorFile $sectionName $tmpFile $osFile' -Verb runas" + """.trimIndent()) + project.exec { + it.standardInput = System.`in` + it.commandLine("cmd", "/C", scriptFile.toString()) + } + } else { + val scriptFile = environment.rootDir.get().asFile.resolve("hosts") + scriptFile.writeText(""" + #!/bin/sh + osascript -e "do shell script \"java -jar $editorFile $sectionName $tmpFile $osFile\" with prompt \"Gradle Environment Hosts\" with administrator privileges" + """.trimIndent()) + project.exec { + it.standardInput = System.`in` + it.commandLine("sh", scriptFile.toString()) + } + } } init { From ae860ea5fdcc48d3391f31a761fbd3ad3ad81bbd Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Wed, 23 Sep 2020 08:14:57 +0200 Subject: [PATCH 2/5] Hosts updater RC --- .../gradle/environment/hosts/Host.kt | 15 ++-- .../gradle/environment/hosts/HostOptions.kt | 23 ++--- .../gradle/environment/hosts/HostUpdater.kt | 84 +++++++++++++++++++ .../environment/tasks/EnvironmentHosts.kt | 33 +------- 4 files changed, 102 insertions(+), 53 deletions(-) create mode 100644 src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt diff --git a/src/main/kotlin/com/cognifide/gradle/environment/hosts/Host.kt b/src/main/kotlin/com/cognifide/gradle/environment/hosts/Host.kt index 3946645..fb2ab95 100644 --- a/src/main/kotlin/com/cognifide/gradle/environment/hosts/Host.kt +++ b/src/main/kotlin/com/cognifide/gradle/environment/hosts/Host.kt @@ -11,14 +11,7 @@ class Host(val url: String) { val config = URL(url) - init { - if (url.isBlank()) { - throw EnvironmentException("Host URL cannot be blank!") - } - } - - val text: String - get() = "$ip\t${config.host}" + val text: String get() = "$ip\t${config.host}" fun tag(id: String) { tags.add(id) @@ -30,5 +23,11 @@ class Host(val url: String) { fun tag(vararg ids: String) = tag(ids.asIterable()) + init { + if (url.isBlank()) { + throw EnvironmentException("Host URL cannot be blank!") + } + } + override fun toString(): String = "Host(url='$url', ip='$ip', tags=$tags)" } diff --git a/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostOptions.kt b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostOptions.kt index 38a82e7..df0b44f 100644 --- a/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostOptions.kt +++ b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostOptions.kt @@ -1,14 +1,14 @@ package com.cognifide.gradle.environment.hosts -import com.cognifide.gradle.environment.EnvironmentExtension +import com.cognifide.gradle.common.utils.using import com.cognifide.gradle.environment.EnvironmentException -import org.gradle.internal.os.OperatingSystem +import com.cognifide.gradle.environment.EnvironmentExtension import java.io.Serializable /** * Manages host definitions in case of different purposes indicated by tags. */ -class HostOptions(environment: EnvironmentExtension) : Serializable { +class HostOptions(private val environment: EnvironmentExtension) : Serializable { val docker = environment.docker @@ -22,17 +22,6 @@ class HostOptions(environment: EnvironmentExtension) : Serializable { convention(common.obj.provider { docker.runtime.hostIp }) } - val osFile = common.obj.string { - convention(common.obj.provider { - when { - OperatingSystem.current().isWindows -> """C:\Windows\System32\drivers\etc\hosts""" - else -> "/etc/hosts" - } - }) - } - - val appendix: String get() = defined.get().joinToString("\n") { it.text } - operator fun String.invoke(options: Host.() -> Unit = {}) = define(this, options) operator fun String.invoke(vararg tags: String) = define(this) { tag(tags.asIterable()) } @@ -61,4 +50,10 @@ class HostOptions(environment: EnvironmentExtension) : Serializable { fun all(tags: Iterable) = defined.get().filter { h -> tags.all { t -> h.tags.contains(t) } }.ifEmpty { throw EnvironmentException("Environment has no hosts tagged with '${tags.joinToString(",")}'!") } + + val updater by lazy { HostUpdater(environment) } + + fun updater(options: HostUpdater.() -> Unit) = updater.using(options) + + fun update() = updater.update() } diff --git a/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt new file mode 100644 index 0000000..6d30749 --- /dev/null +++ b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt @@ -0,0 +1,84 @@ +package com.cognifide.gradle.environment.hosts + +import com.cognifide.gradle.environment.EnvironmentExtension +import org.gradle.internal.os.OperatingSystem + +class HostUpdater(val environment: EnvironmentExtension) { + + private val project = environment.project + + private val logger = project.logger + + private val common = environment.common + + val workDir = common.obj.dir { + convention(environment.rootDir.dir("hosts")) + common.prop.file("environment.hosts.updater.workDir")?.let { set(it) } + } + + val targetFile = common.obj.file { + fileProvider(common.obj.provider { + project.file(when { + OperatingSystem.current().isWindows -> """C:\Windows\System32\drivers\etc\hosts""" + else -> "/etc/hosts" + }) + }) + common.prop.file("environment.hosts.updater.targetFile")?.let { set(it) } + } + + val section = common.obj.string { + convention(environment.docker.stack.internalName) + common.prop.string("environment.hosts.updater.section")?.let { set(it) } + } + + @Suppress("MaxLineLength") + fun update() { + val os = OperatingSystem.current() + val osFile = targetFile.get() + + val dir = workDir.get().asFile.apply { mkdirs() } + + val entriesFile = dir.resolve("hosts.txt").apply { + logger.info("Generating hosts entries file: $this") + writeText(environment.hosts.defined.get().joinToString(System.lineSeparator()) { it.text }) + } + val updaterJar = dir.resolve("hosts.jar").apply { + logger.info("Providing hosts updater program: $this") + outputStream().use { output -> + this@HostUpdater.javaClass.getResourceAsStream("/hosts.jar").use { + input -> input.copyTo(output) + } + } + } + val sectionName = section.get() + + if (os.isWindows) { + val scriptFile = dir.resolve("hosts.bat") + logger.info("Generating hosts updating script: $scriptFile") + + scriptFile.writeText(""" + powershell -command "Start-Process cmd -ArgumentList '/C cd %CD% && java -jar $updaterJar $sectionName $entriesFile $osFile' -Verb runas" + """.trimIndent()) + project.exec { it.commandLine("cmd", "/C", scriptFile.toString()) } + logger.lifecycle("Environment hosts successfully updated.") + } else { + val scriptFile = dir.resolve("hosts.sh") + logger.info("Generating hosts updating script: $scriptFile") + + if (os.isMacOsX) { + scriptFile.writeText(""" + #!/bin/sh + osascript -e "do shell script \"java -jar $updaterJar $sectionName $entriesFile $osFile\" with prompt \"Gradle Environment Hosts\" with administrator privileges" + """.trimIndent()) + project.exec { it.commandLine("sh", scriptFile.toString()) } + logger.lifecycle("Environment hosts successfully updated.") + } else { + scriptFile.writeText(""" + #!/bin/sh + java -jar $updaterJar $sectionName $entriesFile $osFile + """.trimIndent()) + logger.lifecycle("To update environment hosts, run script below as administrator/super-user:\n$scriptFile") + } + } + } +} diff --git a/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt b/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt index 450b2f7..b7a1842 100644 --- a/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt +++ b/src/main/kotlin/com/cognifide/gradle/environment/tasks/EnvironmentHosts.kt @@ -1,46 +1,17 @@ package com.cognifide.gradle.environment.tasks import com.cognifide.gradle.environment.EnvironmentDefaultTask -import org.buildobjects.process.ProcBuilder import org.gradle.api.tasks.TaskAction -import org.gradle.internal.os.OperatingSystem open class EnvironmentHosts : EnvironmentDefaultTask() { @TaskAction fun appendHosts() { - val tmpFile = environment.rootDir.get().asFile.resolve("hosts.txt").apply { - writeText(environment.hosts.appendix) - } - val osFile = environment.hosts.osFile.get() - - val sectionName = environment.docker.stack.internalName - val editorFile = environment.rootDir.get().asFile.resolve("hosts.jar") - - if (OperatingSystem.current().isWindows) { - val scriptFile = environment.rootDir.get().asFile.resolve("hosts.bat") - scriptFile.writeText(""" - powershell -command "Start-Process cmd -ArgumentList '/C cd %CD% && java -jar $editorFile $sectionName $tmpFile $osFile' -Verb runas" - """.trimIndent()) - project.exec { - it.standardInput = System.`in` - it.commandLine("cmd", "/C", scriptFile.toString()) - } - } else { - val scriptFile = environment.rootDir.get().asFile.resolve("hosts") - scriptFile.writeText(""" - #!/bin/sh - osascript -e "do shell script \"java -jar $editorFile $sectionName $tmpFile $osFile\" with prompt \"Gradle Environment Hosts\" with administrator privileges" - """.trimIndent()) - project.exec { - it.standardInput = System.`in` - it.commandLine("sh", scriptFile.toString()) - } - } + environment.hosts.update() } init { - description = "Prints environment hosts entries." + description = "Updates environment hosts entries." } companion object { From 0056fa4ed469a466e41f61e4e37e08ac3101690b Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Wed, 23 Sep 2020 08:25:26 +0200 Subject: [PATCH 3/5] Bump --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4537e4b..7bb98db 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("com.cognifide.gradle:common-plugin:0.1.64") + implementation("com.cognifide.gradle:common-plugin:0.1.63") implementation("org.buildobjects:jproc:2.3.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5") implementation("org.apache.commons:commons-lang3:3.9") From 2ff081f48929281ab7841800b6552837a9d1c086 Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Wed, 23 Sep 2020 09:18:57 +0200 Subject: [PATCH 4/5] Hosts updater done --- hosts/src/main/kotlin/main.kt | 7 ++++++- .../cognifide/gradle/environment/hosts/HostUpdater.kt | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hosts/src/main/kotlin/main.kt b/hosts/src/main/kotlin/main.kt index 1c89489..3bf3c56 100644 --- a/hosts/src/main/kotlin/main.kt +++ b/hosts/src/main/kotlin/main.kt @@ -1,6 +1,6 @@ import java.io.File -fun main(args: Array) { +fun main(args: Array) = try { val sourceName = args.getOrNull(0) ?: "mysite" val sourceFile = File(args.getOrNull(1) ?: ".gradle/environment/hosts.txt") val sourceSection = Section(sourceName, sourceFile.readText().lines().map { it.trim() }) @@ -10,11 +10,16 @@ fun main(args: Array) { val sections = Section.parseAll(text) val targetSection = sections.find { it.name == sourceSection.name } + if (targetSection != null) { targetFile.writeText(text.replace(targetSection.render(), sourceSection.render())) } else { targetFile.appendText("${System.lineSeparator()}${sourceSection.render()}") } +} catch (e: Exception) { + println("Cannot update hosts file!") + println("Ensure using administrator/super-user privileges.") + println("Error details: ${e.message}") } data class Section(val name: String, val entries: List) { diff --git a/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt index 6d30749..1177441 100644 --- a/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt +++ b/src/main/kotlin/com/cognifide/gradle/environment/hosts/HostUpdater.kt @@ -11,6 +11,11 @@ class HostUpdater(val environment: EnvironmentExtension) { private val common = environment.common + val interactive = common.obj.boolean { + convention(true) + common.prop.boolean("environment.hosts.updater.interactive")?.let { set(it) } + } + val workDir = common.obj.dir { convention(environment.rootDir.dir("hosts")) common.prop.file("environment.hosts.updater.workDir")?.let { set(it) } @@ -52,7 +57,7 @@ class HostUpdater(val environment: EnvironmentExtension) { } val sectionName = section.get() - if (os.isWindows) { + if (os.isWindows && interactive.get()) { val scriptFile = dir.resolve("hosts.bat") logger.info("Generating hosts updating script: $scriptFile") @@ -65,7 +70,7 @@ class HostUpdater(val environment: EnvironmentExtension) { val scriptFile = dir.resolve("hosts.sh") logger.info("Generating hosts updating script: $scriptFile") - if (os.isMacOsX) { + if (os.isMacOsX && interactive.get()) { scriptFile.writeText(""" #!/bin/sh osascript -e "do shell script \"java -jar $updaterJar $sectionName $entriesFile $osFile\" with prompt \"Gradle Environment Hosts\" with administrator privileges" From 8fceb3b07885dfa454709a9fed072922628a383c Mon Sep 17 00:00:00 2001 From: Krystian Panek Date: Wed, 23 Sep 2020 09:19:54 +0200 Subject: [PATCH 5/5] Bump --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7bf8d81..cadfe26 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version=1.0.9 +version=1.1.0 release.useAutomaticVersion=true \ No newline at end of file