Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ktx-serialization = "1.3.1"
ktor = "2.0.0-beta-1"
junixsocket = "2.4.0"
kotest = "5.0.3"
ktx-datetime = "0.3.1"

[libraries.ktx-coroutines-core]
module = "org.jetbrains.kotlinx:kotlinx-coroutines-core"
Expand Down Expand Up @@ -78,6 +79,10 @@ version.ref = "kotest"
module = "io.kotest:kotest-runner-junit5-jvm"
version.ref = "kotest"

[libraries.ktx-datetime]
module = "org.jetbrains.kotlinx:kotlinx-datetime"
version.ref = "ktx-datetime"

[bundles]
ktor = ["ktor-client-core", "ktor-client-okhttp", "ktor-client-serialization", "ktor-client-json", "ktor-network", "ktor-client-content-negotiation", "ktor-serialization-kotlinx-json"]
ktx = ["ktx-coroutines-core", "ktx-serialization-core", "ktx-serialization-json"]
Expand Down
10 changes: 5 additions & 5 deletions yoki-engine-docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
* [ ] Delete unused networks - POST **/networks/prune**

### Volumes
* [ ] List volumes - GET **/volumes**
* [ ] Create a volume - POST **/volumes/create**
* [ ] Inspect a volume - GET **/volumes/:name**
* [ ] Remove a volume - DELETE **/volumes/:name**
* [ ] Delete unused volumes - POST **/volumes/prune**
* [x] List volumes - GET **/volumes**
* [x] Create a volume - POST **/volumes/create**
* [x] Inspect a volume - GET **/volumes/:name**
* [x] Remove a volume - DELETE **/volumes/:name**
* [x] Delete unused volumes - POST **/volumes/prune**

### Exec
* [ ] Start an exec instance - POST **/exec/:id/start**
Expand Down
1 change: 1 addition & 0 deletions yoki-engine-docker/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ kotlin {
implementation(project(":yoki-protocol"))
implementation(libs.bundles.ktor)
implementation(libs.bundles.ktx)
implementation(libs.ktx.datetime)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.katan.yoki.engine.docker.model
package org.katan.yoki.engine.docker.network.model

import kotlinx.serialization.Serializable

/**
* @see Container
*/
@Serializable
public data class DockerContainer(
public data class Container(
val image: String,
val name: String? = null,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.katan.yoki.engine.docker.network.model.volume

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
public data class Volume(
@SerialName("Name") public val name: String,
@SerialName("Driver") public val driver: String,
@SerialName("Scope") public val scope: String,
@SerialName("Mountpoint") public val mountPoint: String,
@SerialName("CreatedAt") public val createdAt: String?,
@SerialName("Labels") public val labels: Map<String, String>,
@SerialName("Options") public val options: Map<String, String>
)

/**
* Filters used in List, Inspect and Prune requests.
*
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.list
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.inspect
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.prune
*/
public const val VolumeFilters: String = "filters"

/**
* Volume definition used in Create request.
*
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.create
*/
public const val VolumeDefinition: String = "definition"

/**
* Volume's name or ID used in Inspect and Remove requests.
*
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.inspect
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.remove
*/
public const val VolumeName: String = "name"

/**
* Parameter used to set if a volume should be force deleted in Remove request
*
* @see org.katan.yoki.engine.docker.resource.volume.VolumeResource.remove
*/
public const val VolumeForceDelete: String = "forceDelete"
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.katan.yoki.engine.docker.network.response.volume

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.katan.yoki.engine.docker.network.model.volume.Volume

@Serializable
public data class VolumeListResponse(
@SerialName("Volumes") public val volumes: Collection<Volume>,
@SerialName("Warnings") public val warnings: Collection<String>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.katan.yoki.engine.docker.network.response.volume

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.katan.yoki.engine.docker.network.model.volume.Volume

@Serializable
public data class VolumePruneResponse(
@SerialName("VolumesDeleted") public val volumesDeleted: Collection<String>,
@SerialName("SpaceReclaimed") public val spaceReclaimed: Long
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import org.katan.yoki.engine.docker.*
import org.katan.yoki.engine.docker.model.*
import org.katan.yoki.engine.docker.network.model.ContainerImage

/**
* @see ContainerResource
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.katan.yoki.engine.docker.resource.volume

import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import org.katan.yoki.engine.docker.DockerEngine
import org.katan.yoki.engine.docker.network.model.volume.*
import org.katan.yoki.engine.docker.network.response.volume.VolumeListResponse
import org.katan.yoki.engine.docker.network.response.volume.VolumePruneResponse

/**
* @see VolumeResource
* @author João Victor Gomides Cruz (devwckd)
*/
public class VolumeResource(
private val engine: DockerEngine
) {

/**
* List volumes
*
* @param options see VolumeList for options.
* @return VolumeListResponse
*
* @see <a href="https://docs.docker.com/engine/api/v1.41/#operation/VolumeList">VolumeList</a>
*/
public suspend fun list(options: Map<String, Any>): VolumeListResponse {
return engine.httpClient.get("/volumes") {
options["filter"]?.let {
parameter(VolumeFilters, options["filter"])
}
}.body()
}

/**
* Create a volume
*
* @param options see VolumeCreate for options.
* @return Volume
*
* @see <a href="https://docs.docker.com/engine/api/v1.41/#operation/VolumeCreate">VolumeCreate</a>
*/
public suspend fun create(options: Map<String, Any>): Volume {
require(VolumeDefinition in options) { "Volume Definition is required" }

return engine.httpClient.post("/volumes/create") {
setBody(options[VolumeDefinition])
}.body()
}

/**
* Inspect a volume
*
* @param options see VolumeInspect for options.
* @return Volume
*
* @see <a href="https://docs.docker.com/engine/api/v1.41/#operation/VolumeInspect">VolumeInspect</a>
*/
public suspend fun inspect(options: Map<String, Any>): Volume {
require(VolumeName in options) { "Volume Name is required" }

return engine.httpClient.get("/volumes/${options[VolumeName]}").body()
}

/**
* Remove a volume
*
* @param options see VolumeDelete for options.
*
* @see <a href="https://docs.docker.com/engine/api/v1.41/#operation/VolumeDelete">VolumeDelete</a>
*/
public suspend fun remove(options: Map<String, Any>) {
require(VolumeName in options) { "Volume Name is required" }

engine.httpClient.delete("/volumes/${options[VolumeName]}") {
options[VolumeForceDelete]?.let {
parameter(VolumeForceDelete, it)
}
}
}

/**
* Delete unused volumes
*
* @param options see VolumePrune for options.
* @return VolumePruneResponse
*
* @see <a href="https://docs.docker.com/engine/api/v1.41/#operation/VolumePrune">VolumePrune</a>
*/
public suspend fun prune(options: Map<String, Any>): VolumePruneResponse {
return engine.httpClient.delete("/volumes/${options[VolumeName]}") {
options[VolumeFilters]?.let {
parameter(VolumeFilters, options["filter"])
}
}.body()
}

}