gradle-ssh-plugin icon indicating copy to clipboard operation
gradle-ssh-plugin copied to clipboard

Kotlin DSL support

Open Skyr opened this issue 6 years ago • 12 comments

Currently, the configuration is done via Groovy delegates. This maps badly to Kotlin. Is there any way to configure the plugin via the Kotlin DSL? Of course, a direct support of the Kotlin DSL would be a dream :-)

Skyr avatar Nov 12 '18 15:11 Skyr

Can anyone give an example of how to use this plugin from .kts at least without DSL?

tanmatra avatar Dec 28 '18 09:12 tanmatra

@tanmatra See https://github.com/gradle/kotlin-dsl/issues/763#issuecomment-423356328

calvertdw avatar Feb 01 '19 21:02 calvertdw

There are two points about making this plugin work with the Kotlin DSL, or making it usable from another plugin implemented in Java or Kotlin:

  • Closure taking methods should be overloaded with type-safe counterparts like Action<T>
  • DSL types shouldn't use Groovy traits as they confuse Java and Kotlin compilers and simply prevent using this plugin, e.g. Remote

See https://github.com/gradle/kotlin-dsl/issues/763

eskatos avatar Apr 19 '19 17:04 eskatos

At the moment i created few extension that makes a little easier to use the plugin:

fun Service.runSessions(action: RunHandler.() -> Unit) =
    run(delegateClosureOf(action))

fun RunHandler.session(vararg remotes: Remote, action: SessionHandler.() -> Unit) =
    session(*remotes, delegateClosureOf(action))

fun SessionHandler.put(from: Any, into: Any) =
    put(hashMapOf("from" to from, "into" to into))

So that i can do something like:

val raspiLocal = remotes.create("raspi-local") {
    val raspiPassword: String by project
    host = "192.168.1.101"
    user = "pi"
    password = raspiPassword
}

ssh.runSessions {
    session(raspiLocal) {
        put(installDist.destinationDir, "~/workspace/dragalia-telegram-bot")
        execute("sudo service dragalia-telegram-bot restart")
    }
}

It works like a charm! https://github.com/lamba92/dragalia-telegram-bot/blob/master/build.gradle.kts

lamba92 avatar Oct 29 '19 22:10 lamba92

Without extensions:

tasks.create(name = "deploy-war") {
    
    group = "deploy"

    val myServer = remotes.create("my-server") {
        host = "10.10.10.10"
        user = "root"
        password = "root"
    }
    
    /* or
    val myServer = org.hidetake.groovy.ssh.core.Remote(
            mapOf<String, String>("host" to "10.10.10.10",
                                  "user" to "root",
                                  "password" to "root"))
    */
    
    doLast {
        ssh.run(delegateClosureOf<org.hidetake.groovy.ssh.core.RunHandler> {
            session(myServer, delegateClosureOf<org.hidetake.groovy.ssh.session.SessionHandler> {
                put(hashMapOf("from" to tasks.getByName<War>("war").archiveFile.get().asFile, "into" to "/path/to/directory"))
            })
        })
    }
}

Eng-Fouad avatar May 06 '20 13:05 Eng-Fouad

An alternative to a whacky Kotlin implementation could be that one isolates the functionality of the SSH plugin into a separate custom task, written in Groovy, and then register / wire that task from the Kotlin build script side. This works best when the custom task resides in buildSrc and when Gradle 6.1 or later is used, so the Kotlin buildscript compilation can be made dependent on the output of the Groovy compiler, like so:

plugins {
    groovy
    `kotlin-dsl`
}

...

tasks.named<GroovyCompile>("compileGroovy") {
    classpath = sourceSets.main.get().compileClasspath
}
tasks.named<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileKotlin") {
    classpath += files(conventionOf(sourceSets.main.get()).getPlugin(GroovySourceSet::class.java).groovy.classesDirectory)
}

(Reference: https://docs.gradle.org/6.1-rc-1/release-notes.html#compilation-order)

realdadfish avatar Jul 20 '20 21:07 realdadfish

I just came across https://github.com/steklopod/gradle-ssh-plugin

gaara87 avatar Jan 01 '21 21:01 gaara87

I just came across https://github.com/steklopod/gradle-ssh-plugin

This references this plugin, so no, it's not an alternative.

realdadfish avatar Feb 09 '21 16:02 realdadfish

I write this code, and it works successfully.

//Deploy Function
tasks.create(name = "deployBootJar")  {
    group = "deploy"
    dependsOn(":bootJar")
    val artifactId = project.name
    val version = project.version
    val port = 8206
    val serverAppPath = "/docker/fs/apps"
    val host = "host"
    val user = "user"
    val password = "password"
    val myServer = Remote(mapOf<String, String>("host" to host,
                                  "user" to user,
                                  "password" to password))
    doLast {
        ssh.run(delegateClosureOf<RunHandler> {
            session(myServer, delegateClosureOf<SessionHandler> {
                execute("mkdir -p ${serverAppPath}/${artifactId}")
                execute("""
                        cat>${serverAppPath}/${artifactId}/docker-compose.yml<<EOF
                        version: '3.9'
                        services:
                          $artifactId:
                            image: jarboot17:GA
                            container_name: $artifactId
                            restart: always
                            volumes:
                              - ${serverAppPath}/${artifactId}/${artifactId}-${version}.jar:/app.jar
                            ports:
                              - ${port}:${port}
                        EOF
                        """.trimIndent())
                put(hashMapOf(
                    "from" to File("${projectDir}/build/libs/${artifactId}-${version}.jar"),
                    "into" to "${serverAppPath}/${artifactId}/${artifactId}-${version}.jar"))
                execute("cd ${serverAppPath}/${artifactId};docker-compose up -d $artifactId")
            })
        })
    }
}

natsufumij avatar Aug 15 '23 11:08 natsufumij

How would I configure the ssh settings ?

nothing seems to work oO I want to change the known hosts file, but it will always user the default settings knownHosts: new File("${System.properties['user.home']}/.ssh/known_hosts"),

if have tried:

tasks.create("deploy") {

        val myServer = Remote(
                mapOf<String, String>(
                        "host" to "192.168.1.1",
                        "user" to "username",
                        "password" to "password"))


        doLast {

            ssh.run(delegateClosureOf<RunHandler> {
                settings(
                        delegateClosureOf<PerServiceSettings>{
                            mapOf(
                                    "knownHosts" to AllowAnyHosts.instance,

                                    )
                        }
                )
                session(
                        myServer,
                        delegateClosureOf<SessionHandler> {
                    put(
                            hashMapOf(
                                    "from" to "${project.rootDir}/deploy",
                                    "into" to "/home/username/"))
                })
            })
        }

    }

and

tasks.create("deploy") {

        val myServer = Remote(
                mapOf<String, String>(
                        "host" to "192.168.1.1",
                        "user" to "username",
                        "password" to "password"))
ssh.settings (
                    delegateClosureOf<GlobalSettings>{
                        mapOf(
                                "knownHosts" to AllowAnyHosts.instance,

                        )
                    }
            )


        doLast {

            ssh.run(delegateClosureOf<RunHandler> {

                session(
                        myServer,
                        delegateClosureOf<SessionHandler> {
                    put(
                            hashMapOf(
                                    "from" to "${project.rootDir}/deploy",
                                    "into" to "/home/username/"))
                })
            })
        }

    }

aminabromand avatar Aug 24 '23 07:08 aminabromand

Had the same issue for trying to set knownHosts for GlobalSettings through closure (/delegateOf). Instead I just added knownHosts property to the Remote(mapOf()) function and it works like a charm.

hmmlopez avatar Jan 23 '24 12:01 hmmlopez

Here is the code that worked for me. With a bit better formatting.

tasks.create("deploy") {
    val myServer = Remote(
        mutableMapOf<String, Any>(
            "host" to "192.168.59.7",
            "user" to "shalva",
            "password" to "yourPassword",
            "knownHosts" to AllowAnyHosts.instance
        )
    )

    doLast {
        ssh.run(delegateClosureOf<RunHandler> {
            session(
                myServer,
                delegateClosureOf<SessionHandler> {
                    put(
                        hashMapOf(
                            "from" to "${project.rootDir}/build/bin/linuxArm64/debugExecutable/untitled.kexe",
                            "into" to "/home/shalva/" // Dont use ~, it does not work
                        )
                    )
                })
        })
    }
}

shalva97 avatar Mar 23 '24 19:03 shalva97