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")
            }
        }
    }
}