Skip to content

Commit

Permalink
Docker image build endpoint implementation (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
DevNatan authored Feb 5, 2024
1 parent 2a80524 commit 39756ee
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 2 deletions.
130 changes: 130 additions & 0 deletions api/yoki.api
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
public final class MainKt {
public static final fun main ()V
public static synthetic fun main ([Ljava/lang/String;)V
}

public final class me/devnatan/yoki/Yoki : kotlinx/coroutines/CoroutineScope {
public fun <init> ()V
public fun <init> (Lme/devnatan/yoki/YokiConfig;)V
Expand Down Expand Up @@ -1029,6 +1034,37 @@ public final class me/devnatan/yoki/models/ProcessConfig$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class me/devnatan/yoki/models/RegistryConfig {
public static final field Companion Lme/devnatan/yoki/models/RegistryConfig$Companion;
public synthetic fun <init> (ILjava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lme/devnatan/yoki/models/RegistryConfig;
public static synthetic fun copy$default (Lme/devnatan/yoki/models/RegistryConfig;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/devnatan/yoki/models/RegistryConfig;
public fun equals (Ljava/lang/Object;)Z
public final fun getPassword ()Ljava/lang/String;
public final fun getUsername ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public static final synthetic fun write$Self (Lme/devnatan/yoki/models/RegistryConfig;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
}

public final class me/devnatan/yoki/models/RegistryConfig$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Lme/devnatan/yoki/models/RegistryConfig$$serializer;
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lme/devnatan/yoki/models/RegistryConfig;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lme/devnatan/yoki/models/RegistryConfig;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class me/devnatan/yoki/models/RegistryConfig$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class me/devnatan/yoki/models/ResizeTTYOptions {
public static final field Companion Lme/devnatan/yoki/models/ResizeTTYOptions$Companion;
public fun <init> ()V
Expand Down Expand Up @@ -2351,6 +2387,95 @@ public final class me/devnatan/yoki/models/image/Image$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class me/devnatan/yoki/models/image/ImageBuildOptions {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/util/List;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/util/List;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component10 ()Ljava/lang/Boolean;
public final fun component11 ()Ljava/lang/Integer;
public final fun component12 ()Ljava/lang/Integer;
public final fun component13 ()Ljava/lang/Integer;
public final fun component14 ()Ljava/lang/String;
public final fun component15 ()Ljava/lang/Integer;
public final fun component16 ()Ljava/lang/Integer;
public final fun component17 ()Ljava/util/Map;
public final fun component18 ()Ljava/lang/Integer;
public final fun component19 ()Ljava/lang/Boolean;
public final fun component2 ()Ljava/lang/String;
public final fun component20 ()Ljava/util/Map;
public final fun component21 ()Ljava/lang/String;
public final fun component22 ()Ljava/lang/String;
public final fun component23 ()Ljava/lang/String;
public final fun component24 ()Ljava/lang/String;
public final fun component25 ()Ljava/lang/String;
public final fun component26 ()Ljava/util/Map;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Ljava/lang/Boolean;
public final fun component6 ()Ljava/lang/Boolean;
public final fun component7 ()Ljava/util/List;
public final fun component8 ()Ljava/lang/String;
public final fun component9 ()Ljava/lang/Boolean;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/util/List;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Lme/devnatan/yoki/models/image/ImageBuildOptions;
public static synthetic fun copy$default (Lme/devnatan/yoki/models/image/ImageBuildOptions;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/util/List;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/Integer;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lme/devnatan/yoki/models/image/ImageBuildOptions;
public fun equals (Ljava/lang/Object;)Z
public final fun getBuildArgs ()Ljava/util/Map;
public final fun getCacheFrom ()Ljava/util/List;
public final fun getCpuPeriod ()Ljava/lang/Integer;
public final fun getCpuQuota ()Ljava/lang/Integer;
public final fun getCpuSetCpus ()Ljava/lang/String;
public final fun getCpuShares ()Ljava/lang/Integer;
public final fun getExtraHosts ()Ljava/lang/String;
public final fun getForceRemoveIntermediateContainers ()Ljava/lang/Boolean;
public final fun getLabels ()Ljava/util/Map;
public final fun getMemoryLimit ()Ljava/lang/Integer;
public final fun getMemorySwap ()Ljava/lang/Integer;
public final fun getNetworkMode ()Ljava/lang/String;
public final fun getNoCache ()Ljava/lang/Boolean;
public final fun getOutputs ()Ljava/lang/String;
public final fun getPath ()Ljava/lang/String;
public final fun getPlatform ()Ljava/lang/String;
public final fun getPull ()Ljava/lang/String;
public final fun getRegistryConfig ()Ljava/util/Map;
public final fun getRemote ()Ljava/lang/String;
public final fun getRemoveIntermediateContainers ()Ljava/lang/Boolean;
public final fun getShmSize ()Ljava/lang/Integer;
public final fun getSquash ()Ljava/lang/Boolean;
public final fun getSuppressVerbose ()Ljava/lang/Boolean;
public final fun getTag ()Ljava/lang/String;
public final fun getTarget ()Ljava/lang/String;
public final fun getVersion ()Ljava/lang/String;
public fun hashCode ()I
public final fun setBuildArgs (Ljava/util/Map;)V
public final fun setCacheFrom (Ljava/util/List;)V
public final fun setCpuPeriod (Ljava/lang/Integer;)V
public final fun setCpuQuota (Ljava/lang/Integer;)V
public final fun setCpuSetCpus (Ljava/lang/String;)V
public final fun setCpuShares (Ljava/lang/Integer;)V
public final fun setExtraHosts (Ljava/lang/String;)V
public final fun setForceRemoveIntermediateContainers (Ljava/lang/Boolean;)V
public final fun setLabels (Ljava/util/Map;)V
public final fun setMemoryLimit (Ljava/lang/Integer;)V
public final fun setMemorySwap (Ljava/lang/Integer;)V
public final fun setNetworkMode (Ljava/lang/String;)V
public final fun setNoCache (Ljava/lang/Boolean;)V
public final fun setOutputs (Ljava/lang/String;)V
public final fun setPath (Ljava/lang/String;)V
public final fun setPlatform (Ljava/lang/String;)V
public final fun setPull (Ljava/lang/String;)V
public final fun setRegistryConfig (Ljava/util/Map;)V
public final fun setRemote (Ljava/lang/String;)V
public final fun setRemoveIntermediateContainers (Ljava/lang/Boolean;)V
public final fun setShmSize (Ljava/lang/Integer;)V
public final fun setSquash (Ljava/lang/Boolean;)V
public final fun setSuppressVerbose (Ljava/lang/Boolean;)V
public final fun setTag (Ljava/lang/String;)V
public final fun setTarget (Ljava/lang/String;)V
public final fun setVersion (Ljava/lang/String;)V
public fun toString ()Ljava/lang/String;
}

public final class me/devnatan/yoki/models/image/ImageKt {
public static final fun getCreated (Lme/devnatan/yoki/models/image/Image;)Lkotlinx/datetime/Instant;
}
Expand Down Expand Up @@ -3915,6 +4040,7 @@ public final class me/devnatan/yoki/resource/image/ImageNotFoundException : me/d

public final class me/devnatan/yoki/resource/image/ImageResource {
public static final field Companion Lme/devnatan/yoki/resource/image/ImageResource$Companion;
public final fun build (Ljava/lang/String;Lme/devnatan/yoki/models/image/ImageBuildOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun list (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun pull (Ljava/lang/String;)Lkotlinx/coroutines/flow/Flow;
public final fun remove (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand All @@ -3924,6 +4050,10 @@ public final class me/devnatan/yoki/resource/image/ImageResource {
public final class me/devnatan/yoki/resource/image/ImageResource$Companion {
}

public final class me/devnatan/yoki/resource/image/ImageResourceKt {
public static final fun build (Lme/devnatan/yoki/resource/image/ImageResource;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class me/devnatan/yoki/resource/network/NetworkResource {
public static final field BASE_PATH Ljava/lang/String;
public final fun connectContainer (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down
12 changes: 12 additions & 0 deletions src/commonMain/kotlin/me/devnatan/yoki/models/RegistryConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package me.devnatan.yoki.models

import kotlinx.serialization.Serializable

/**
* Configuration for Docker registry authentication.
*
* @property username The username for authentication with the Docker registry.
* @property password The password for authentication with the Docker registry.
*/
@Serializable
public data class RegistryConfig(val username: String, val password: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package me.devnatan.yoki.models.image

import me.devnatan.yoki.models.RegistryConfig

/**
* Options for building a Docker image.
*
* @property path The path to the build context.
* @property tag The tag to be applied to the built image.
* @property extraHosts Additional hosts to add to /etc/hosts in the build containers.
* @property remote URL of the Docker daemon to connect to.
* @property suppressVerbose Suppress verbose output during build.
* @property noCache Do not use the cache when building the image.
* @property cacheFrom List of images used for cache resolution.
* @property pull Always attempt to pull a newer version of the image.
* @property removeIntermediateContainers Remove intermediate containers after a successful build.
* @property forceRemoveIntermediateContainers Force removal of intermediate containers.
* @property memoryLimit Memory limit for the build container.
* @property memorySwap Swap limit equal to memory plus swap.
* @property cpuShares CPU shares for the build container.
* @property cpuSetCpus CPUs in which to allow execution.
* @property cpuPeriod CPU period to be used for the build container.
* @property cpuQuota CPU quota to be used for the build container.
* @property buildArgs Build-time variables to set during the build.
* @property shmSize Size of /dev/shm in bytes.
* @property squash Squash newly built layers into a single new layer.
* @property labels User-defined key-value metadata to add to the image.
* @property networkMode Network mode for the build container.
* @property platform Platform in the format os[/arch[/variant]].
* @property target Build only a specific target stage.
* @property outputs Specify the outputs to be built.
* @property version Version of the build options.
* @property registryConfig Docker registry auth configurations for multiple registries that a build may refer to.
*/
public data class ImageBuildOptions(
public var path: String? = null,
public var tag: String? = null,
public var extraHosts: String? = null,
public var remote: String? = null,
public var suppressVerbose: Boolean? = null,
public var noCache: Boolean? = null,
public var cacheFrom: List<String> = emptyList(),
public var pull: String? = null,
public var removeIntermediateContainers: Boolean? = null,
public var forceRemoveIntermediateContainers: Boolean? = null,
public var memoryLimit: Int? = null,
public var memorySwap: Int? = null,
public var cpuShares: Int? = null,
public var cpuSetCpus: String? = null,
public var cpuPeriod: Int? = null,
public var cpuQuota: Int? = null,
public var buildArgs: Map<String, String> = emptyMap(),
public var shmSize: Int? = null,
public var squash: Boolean? = null,
public var labels: Map<String, String> = emptyMap(),
public var networkMode: String? = null,
public var platform: String? = null,
public var target: String? = null,
public var outputs: String? = null,
public var version: String? = null,
public var registryConfig: Map<String, RegistryConfig> = emptyMap(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,33 @@ import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.parameter
import io.ktor.client.request.post
import io.ktor.client.request.preparePost
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.readUTF8Line
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import me.devnatan.yoki.models.image.ImageBuildOptions
import me.devnatan.yoki.models.image.ImagePull
import me.devnatan.yoki.models.image.ImageSummary

private const val BASE_PATH = "/images"

public class ImageResource internal constructor(
private val httpClient: HttpClient,
private val json: Json,
) {

public companion object {
private const val BASE_PATH = "/images"

private val TAR_CONTENT_TYPE = ContentType.parse("application/x-tar")
}

public suspend fun list(): List<ImageSummary> {
Expand All @@ -45,4 +54,47 @@ public class ImageResource internal constructor(
parameter("noprune", noprune)
}
}

/**
* builds a Docker image using the specified archive path and [ImageBuildOptions].
*
* @param archivePath The path to the build context archive (e.g., a TAR file) that contains the source code and resources.
* @param options The [ImageBuildOptions] containing the configuration for the image build.
*/
public suspend fun build(archivePath: String, options: ImageBuildOptions) {
httpClient.post("/build") {
contentType(TAR_CONTENT_TYPE)
header("X-Registry-Config", json.encodeToString(options.registryConfig))
parameter("dockerfile", options.path)
parameter("t", options.tag)
parameter("extrahosts", options.extraHosts)
parameter("remote", options.remote)
parameter("q", options.suppressVerbose)
parameter("nocache", options.noCache)
parameter("cachefrom", options.cacheFrom)
parameter("pull", options.pull)
parameter("rm", options.removeIntermediateContainers)
parameter("forcerm", options.forceRemoveIntermediateContainers)
parameter("memory", options.memoryLimit)
parameter("memswap", options.memorySwap)
parameter("cpushares", options.cpuShares)
parameter("cpusetcpus", options.cpuSetCpus)
parameter("cpuperiod", options.cpuPeriod)
parameter("cpuquota", options.cpuQuota)
parameter("buildargs", options.buildArgs)
parameter("shmsize", options.shmSize)
parameter("squash", options.squash)
parameter("labels", options.labels)
parameter("networkmode", options.networkMode)
parameter("platform", options.platform)
parameter("target", options.target)
parameter("outputs", options.outputs)
parameter("version", options.version)
setBody(archivePath)
}
}
}

public suspend inline fun ImageResource.build(archivePath: String, options: ImageBuildOptions.() -> Unit) {
build(archivePath, ImageBuildOptions().apply(options))
}

0 comments on commit 39756ee

Please sign in to comment.