Cloud API Kotlin
Solidblocks hetzner-cloud is Kotlin implementation for the Hetzner Cloud API.
Usage
To use Solidblocks hetzner-cloud just add the dependency to your Gradle or Maven build
build.gradle.kts
plugins {
id("org.jetbrains.kotlin.jvm") version "2.2.10"
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("de.solidblocks:hetzner-cloud:0.4.15")
}
tasks.named<Test>("test") {
useJUnitPlatform()
}Info
The implementation is currently driven by the needs of other projects I am working and, and does not yet fully cover all API endpoints. See development chapter on how to add missing features.
Basics
The library supports Kotlin coroutines, thus all API calls must be made from a coroutine context. The root api has to be initialized using a Hetzner cloud api token, from there all supports resources are available grouped by resource type.
package de.solidblocks.hetzner
import de.solidblocks.hetzner.cloud.HetznerApi
import kotlinx.coroutines.runBlocking
fun BasicUsage() {
runBlocking {
val api = HetznerApi(System.getenv("HCLOUD_TOKEN"))
//api.servers.shutdown(123)
//api.firewalls.delete(12)
//api.volumes.create(...)
}
}Create and Get
All resources support listing, as well as filtering by resource attributes or labels
package de.solidblocks.hetzner
import de.solidblocks.hetzner.cloud.HetznerApi
import de.solidblocks.hetzner.cloud.model.HetznerLocation
import de.solidblocks.hetzner.cloud.model.HetznerServerType
import de.solidblocks.hetzner.cloud.resources.ServerCreateRequest
import kotlinx.coroutines.runBlocking
fun CreateAndGetResources() {
runBlocking {
val api = HetznerApi(System.getenv("HCLOUD_TOKEN"))
val server = api.servers.create(
ServerCreateRequest(
"server1",
HetznerLocation.nbg1,
HetznerServerType.cx23,
image = "debian-12",
)
)
val serverByName = api.servers.get("server1") ?: throw RuntimeException("could not find server1")
val serverById = api.servers.get(server.server.id) ?: throw RuntimeException("could not find server with id '${server.server.id}'")
}
}Listing and Filtering
All resources support resource creation and retrieval by name and id.
package de.solidblocks.hetzner
import de.solidblocks.hetzner.cloud.HetznerApi
import de.solidblocks.hetzner.cloud.model.FilterValue
import de.solidblocks.hetzner.cloud.model.LabelSelectorValue.Equals
import de.solidblocks.hetzner.cloud.resources.ImageType
import kotlinx.coroutines.runBlocking
fun Filtering() {
runBlocking {
val api = HetznerApi(System.getenv("HCLOUD_TOKEN"))
// list all images
api.images.list()
// filter by image type
api.images.list(mapOf("type" to FilterValue.Equals(ImageType.app)))
// filter by label
api.servers.list(labelSelectors = mapOf("label1" to Equals("foo-bar")))
}
}Actions
Waiters are available for resources that are created or updated asynchronosly
package de.solidblocks.hetzner
import de.solidblocks.hetzner.cloud.HetznerApi
import de.solidblocks.hetzner.cloud.model.HetznerLocation
import de.solidblocks.hetzner.cloud.model.HetznerServerType
import de.solidblocks.hetzner.cloud.resources.ServerCreateRequest
import kotlinx.coroutines.runBlocking
fun WaitForActions() {
runBlocking {
val api = HetznerApi(System.getenv("HCLOUD_TOKEN"))
val server = api.servers.create(
ServerCreateRequest(
"server1",
HetznerLocation.nbg1,
HetznerServerType.cx23,
image = "debian-12",
)
)
api.servers.waitForAction(server.action)
}
}Exceptions
For failing API calls the exception HetznerApiException provides type access to the underlying Hetzner error.
package de.solidblocks.hetzner
import de.solidblocks.hetzner.cloud.HetznerApi
import de.solidblocks.hetzner.cloud.model.HetznerApiErrorType
import de.solidblocks.hetzner.cloud.model.HetznerApiException
import de.solidblocks.hetzner.cloud.model.HetznerLocation
import de.solidblocks.hetzner.cloud.resources.VolumeCreateRequest
import de.solidblocks.hetzner.cloud.resources.VolumeFormat
import kotlinx.coroutines.runBlocking
fun Exceptions() {
runBlocking {
val api = HetznerApi(System.getenv("HCLOUD_TOKEN"))
try {
api.volumes.create(VolumeCreateRequest("volume1", 16, HetznerLocation.nbg1, VolumeFormat.ext4))
} catch (e: HetznerApiException) {
if (e.error.code == HetznerApiErrorType.RESOURCE_LIMIT_EXCEEDED) {
print("volume quota reached")
}
}
}
}