Kotlin
We recommend reviewing Docker’s best practices before attempting to create a custom plugin.
We recommend that all plugins be placed inside a scratch image.
Overview
From Kotlin documentation:
Kotlin is…
A modern, concise and safe programming language that is easy to pick up, so you can create powerful applications immediately
Code
To create a plugin using Kotlin, we’ll need to first decide what task we want this plugin to accomplish.
For this example, we’re going to create a program that makes an HTTP request from the provided input:
import org.http4k.client.ApacheClient
import org.http4k.core.*
import org.http4k.format.Jackson.auto
import yellowstone.cr.VCRException
fun main() {
// get the vela parameters from env variables
val method = when ("METHOD".parameter.envOrDefault("GET").trim().lowercase()) {
"get" -> Method.GET
"put" -> Method.PUT
"post" -> Method.POST
"delete" -> Method.DELETE
else -> throw Exception("Method not supported")
}
val body = "BODY".parameter.env
val url = "URL".parameter.env
// set up the clientId
val client: HttpHandler = ApacheClient()
// make the request and print the result
println(Request(method, url).addBody(body).okOrDie(client).toObject<String>())
}
// Helper functions
val String.env get() = System.getenv(this) ?: throw VCRException("The environment variable $this is required but missing!")
fun String.envOrDefault(default: String) = System.getenv(this) ?: default
val String.parameter get() = "PARAMETER_$this"
fun Request.okOrDie(client: HttpHandler) = client(this).let { response ->
response.takeIf { it.status.successful }
?: throw Exception("Got unexpected ${response.status.code} from request ${method.name} $uri! ${response.bodyString()}")
}
inline fun <reified T : Any> Response.toObject() = Body.auto<T>().toLens()(this)
inline fun <reified T : Any> Request.addBody(t: T) = Body.auto<T>().toLens()(t, this)
Jar
In order to make this code a runnable executable, you must first turn it into a jar file. Below is an example build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
application
kotlin("jvm") version "1.5.10"
}
repositories {
mavenCentral()
}
application {
group = "mygroup"
mainClass.set("mygroup.MainKt")
}
dependencies {
fun deps(format: String, vararg arr: String) = with(format) { arr.forEach { implementation(format(it)) } }
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
deps("org.http4k:http4k-%s:4.9.9.0", "client-apache", "format-jackson")
}
tasks {
jar {
enabled = true
}
withType<KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_11.majorVersion
}
withType<Test> {
useJUnitPlatform()
}
}
To build the jar, run ./gradlew clean build distTar
Image
Once we have the jar needed to accomplish our plugin’s task, we need to create a Dockerfile to produce an image.
This image should contain the jar and be setup to run that jar when the plugin is executed
FROM alpine:latest
# Install Java 11
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk
ENV PATH $PATH:/usr/lib/jvm/java-11-openjdk/jre/bin:/usr/lib/jvm/java-11-openjdk
RUN apk update && \
apk upgrade && \
apk --no-cache add openjdk11 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
# copy the executable
ADD build/distributions/vela-sample.tar /
CMD ["/vela-sample/bin/vela-sample"]
Publishing
In order to run the plugin in a pipeline, we’ll need to make sure we build and publish it to a Docker registry:
# build the image
docker build -t target/vela-sample:kotlin .
# publish the image
docker push target/vela-sample:kotlin
Troubleshooting
To verify that the plugin performs the desired task, it can be executed locally via the command line:
docker run --rm \
-e PARAMETER_BODY="This is a sample Vela plugin written with Kotlin" \
-e PARAMETER_METHOD="POST" \
-e PARAMETER_URL="http://vela.localhost.com" \
target/vela-sample:kotlin
Usage
After publishing the image to a Docker registry, it can be referenced in a pipeline:
version: "1"
steps:
- name: sample kotlin plugin
image: target/vela-sample:kotlin
pull: always
parameters:
url: http://vela.localhost.com
method: POST
body: |
This is a sample Vela plugin written with Kotlin