This client has 4 appealing properties
- Fully async code no blocking threads.
- Easy to compose both sequentially and concurrently.
- Minimum dependencies.
- Small
This project depends on min-rest-client that is both small and fully non-blocking rest client using suspendable methods to allow easy composition.
To consume this project using maven add the following to your pom.xml
<dependency>
<groupId>com.github.barakb</groupId>
<artifactId>nomad-client</artifactId>
<version>1.0.10</version>
</dependency>
Or gradle
implementation("com.github.barakb:nomad-client:1.0.10")
To create a Nomad client Kotlin DSL can be used.
val client = NomadClient {
address = "http://127.0.0.1:4646"
// optional authToken
authToken = "my-fake-token"
}
Https address can be used as well. The authToken is optional.
The client has public getter for each sub api (jobs, allocations etc), for example this is how a job is submitted.
client.jobs.create(job)
A job can be created directly using the data objects (same as in Java) or using the JobBuilder that give a nicer Kotlin DCL that mimic HCL.
val job = JobBuilder().apply {
id = "foo"
name = "foo"
group {
name = "bar"
task {
raw_exec {
command = "/home/barak/dev/kotlin/nomad-client/job.sh"
}
name = "myTask"
}
}
}.build()
client.jobs.create(job)
Of course, you can use arbitrary Kotlin code in the builder. For example, this is how you can create a Group with 10 tasks.
val job = JobBuilder().apply {
id = "foo"
name = "foo"
group {
name = "bar"
repeat(10) {
task {
raw_exec {
command = "/home/barak/dev/kotlin/nomad-client/job.sh"
}
name = "myTask$it"
}
}
}
}.build()
client.jobs.create(job)
You can also create the Job while sending the request to Nomad.
client.jobs.create {
id = "foo"
name = "foo"
group {
name = "bar"
task {
raw_exec {
command = "/home/barak/dev/kotlin/nomad-client/job.sh"
}
name = "myTask"
}
}
}
A docker task can executed using the docker_exec DSL
fun main(): Unit = runBlocking {
NomadClient {
address = "http://127.0.0.1:4646"
authToken = "my-fake-token"
}.use { client ->
// https://learn.hashicorp.com/tutorials/nomad/jobs-submit
client.jobs.create {
id = "my_job_id"
name = "my_job"
group {
name = "example"
task {
name = "server"
docker_exec {
image = "hashicorp/http-echo"
args = listOf("-listen", ":5678", "-text", "hello world")
}
resource {
network {
mBits = 10
port("http") {
static = 5678
}
}
}
}
}
}
}
}
There are a few utility functions built around Nomad API, for example calling client.jobs.getLastDeploymentIfHealthy(validJob.id, 30.seconds)
will return the healthy deployment of that last version of this job or null if no such exists, wait is an optional parameter.
This is how you can use this function to revert changes to a job after unsuccessful change
@ExperimentalTime
fun main(): Unit = runBlocking {
NomadClient {
address = "http://127.0.0.1:4646"
authToken = "my-fake-token"
}.use { client ->
client.jobs.create(invalidJob)
val deployment = client.jobs.getLastDeploymentIfHealthy(invalidJob.id, 30.seconds)
if (deployment == null) {
logger.info("reverting to a known valid job setup")
client.jobs.create(validJob)
val revertTo = client.jobs.getLastDeploymentIfHealthy(validJob.id, 30.seconds)
logger.info("got deployment: $revertTo")
}
}
}
The following API are implemented
- jobs
- allocations
- nodes
- evaluations
- deployments
- aclTokens
- aclPolicies
- agent
- operator
- search
- volume