Skip to content

Commit 39756ee

Browse files
authored
Docker image build endpoint implementation (#132)
1 parent 2a80524 commit 39756ee

File tree

4 files changed

+258
-2
lines changed

4 files changed

+258
-2
lines changed

api/yoki.api

+130
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
public final class MainKt {
2+
public static final fun main ()V
3+
public static synthetic fun main ([Ljava/lang/String;)V
4+
}
5+
16
public final class me/devnatan/yoki/Yoki : kotlinx/coroutines/CoroutineScope {
27
public fun <init> ()V
38
public fun <init> (Lme/devnatan/yoki/YokiConfig;)V
@@ -1029,6 +1034,37 @@ public final class me/devnatan/yoki/models/ProcessConfig$Companion {
10291034
public final fun serializer ()Lkotlinx/serialization/KSerializer;
10301035
}
10311036

1037+
public final class me/devnatan/yoki/models/RegistryConfig {
1038+
public static final field Companion Lme/devnatan/yoki/models/RegistryConfig$Companion;
1039+
public synthetic fun <init> (ILjava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V
1040+
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
1041+
public final fun component1 ()Ljava/lang/String;
1042+
public final fun component2 ()Ljava/lang/String;
1043+
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lme/devnatan/yoki/models/RegistryConfig;
1044+
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;
1045+
public fun equals (Ljava/lang/Object;)Z
1046+
public final fun getPassword ()Ljava/lang/String;
1047+
public final fun getUsername ()Ljava/lang/String;
1048+
public fun hashCode ()I
1049+
public fun toString ()Ljava/lang/String;
1050+
public static final synthetic fun write$Self (Lme/devnatan/yoki/models/RegistryConfig;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V
1051+
}
1052+
1053+
public final class me/devnatan/yoki/models/RegistryConfig$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
1054+
public static final field INSTANCE Lme/devnatan/yoki/models/RegistryConfig$$serializer;
1055+
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
1056+
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
1057+
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lme/devnatan/yoki/models/RegistryConfig;
1058+
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
1059+
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
1060+
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lme/devnatan/yoki/models/RegistryConfig;)V
1061+
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
1062+
}
1063+
1064+
public final class me/devnatan/yoki/models/RegistryConfig$Companion {
1065+
public final fun serializer ()Lkotlinx/serialization/KSerializer;
1066+
}
1067+
10321068
public final class me/devnatan/yoki/models/ResizeTTYOptions {
10331069
public static final field Companion Lme/devnatan/yoki/models/ResizeTTYOptions$Companion;
10341070
public fun <init> ()V
@@ -2351,6 +2387,95 @@ public final class me/devnatan/yoki/models/image/Image$Companion {
23512387
public final fun serializer ()Lkotlinx/serialization/KSerializer;
23522388
}
23532389

2390+
public final class me/devnatan/yoki/models/image/ImageBuildOptions {
2391+
public fun <init> ()V
2392+
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
2393+
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
2394+
public final fun component1 ()Ljava/lang/String;
2395+
public final fun component10 ()Ljava/lang/Boolean;
2396+
public final fun component11 ()Ljava/lang/Integer;
2397+
public final fun component12 ()Ljava/lang/Integer;
2398+
public final fun component13 ()Ljava/lang/Integer;
2399+
public final fun component14 ()Ljava/lang/String;
2400+
public final fun component15 ()Ljava/lang/Integer;
2401+
public final fun component16 ()Ljava/lang/Integer;
2402+
public final fun component17 ()Ljava/util/Map;
2403+
public final fun component18 ()Ljava/lang/Integer;
2404+
public final fun component19 ()Ljava/lang/Boolean;
2405+
public final fun component2 ()Ljava/lang/String;
2406+
public final fun component20 ()Ljava/util/Map;
2407+
public final fun component21 ()Ljava/lang/String;
2408+
public final fun component22 ()Ljava/lang/String;
2409+
public final fun component23 ()Ljava/lang/String;
2410+
public final fun component24 ()Ljava/lang/String;
2411+
public final fun component25 ()Ljava/lang/String;
2412+
public final fun component26 ()Ljava/util/Map;
2413+
public final fun component3 ()Ljava/lang/String;
2414+
public final fun component4 ()Ljava/lang/String;
2415+
public final fun component5 ()Ljava/lang/Boolean;
2416+
public final fun component6 ()Ljava/lang/Boolean;
2417+
public final fun component7 ()Ljava/util/List;
2418+
public final fun component8 ()Ljava/lang/String;
2419+
public final fun component9 ()Ljava/lang/Boolean;
2420+
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;
2421+
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;
2422+
public fun equals (Ljava/lang/Object;)Z
2423+
public final fun getBuildArgs ()Ljava/util/Map;
2424+
public final fun getCacheFrom ()Ljava/util/List;
2425+
public final fun getCpuPeriod ()Ljava/lang/Integer;
2426+
public final fun getCpuQuota ()Ljava/lang/Integer;
2427+
public final fun getCpuSetCpus ()Ljava/lang/String;
2428+
public final fun getCpuShares ()Ljava/lang/Integer;
2429+
public final fun getExtraHosts ()Ljava/lang/String;
2430+
public final fun getForceRemoveIntermediateContainers ()Ljava/lang/Boolean;
2431+
public final fun getLabels ()Ljava/util/Map;
2432+
public final fun getMemoryLimit ()Ljava/lang/Integer;
2433+
public final fun getMemorySwap ()Ljava/lang/Integer;
2434+
public final fun getNetworkMode ()Ljava/lang/String;
2435+
public final fun getNoCache ()Ljava/lang/Boolean;
2436+
public final fun getOutputs ()Ljava/lang/String;
2437+
public final fun getPath ()Ljava/lang/String;
2438+
public final fun getPlatform ()Ljava/lang/String;
2439+
public final fun getPull ()Ljava/lang/String;
2440+
public final fun getRegistryConfig ()Ljava/util/Map;
2441+
public final fun getRemote ()Ljava/lang/String;
2442+
public final fun getRemoveIntermediateContainers ()Ljava/lang/Boolean;
2443+
public final fun getShmSize ()Ljava/lang/Integer;
2444+
public final fun getSquash ()Ljava/lang/Boolean;
2445+
public final fun getSuppressVerbose ()Ljava/lang/Boolean;
2446+
public final fun getTag ()Ljava/lang/String;
2447+
public final fun getTarget ()Ljava/lang/String;
2448+
public final fun getVersion ()Ljava/lang/String;
2449+
public fun hashCode ()I
2450+
public final fun setBuildArgs (Ljava/util/Map;)V
2451+
public final fun setCacheFrom (Ljava/util/List;)V
2452+
public final fun setCpuPeriod (Ljava/lang/Integer;)V
2453+
public final fun setCpuQuota (Ljava/lang/Integer;)V
2454+
public final fun setCpuSetCpus (Ljava/lang/String;)V
2455+
public final fun setCpuShares (Ljava/lang/Integer;)V
2456+
public final fun setExtraHosts (Ljava/lang/String;)V
2457+
public final fun setForceRemoveIntermediateContainers (Ljava/lang/Boolean;)V
2458+
public final fun setLabels (Ljava/util/Map;)V
2459+
public final fun setMemoryLimit (Ljava/lang/Integer;)V
2460+
public final fun setMemorySwap (Ljava/lang/Integer;)V
2461+
public final fun setNetworkMode (Ljava/lang/String;)V
2462+
public final fun setNoCache (Ljava/lang/Boolean;)V
2463+
public final fun setOutputs (Ljava/lang/String;)V
2464+
public final fun setPath (Ljava/lang/String;)V
2465+
public final fun setPlatform (Ljava/lang/String;)V
2466+
public final fun setPull (Ljava/lang/String;)V
2467+
public final fun setRegistryConfig (Ljava/util/Map;)V
2468+
public final fun setRemote (Ljava/lang/String;)V
2469+
public final fun setRemoveIntermediateContainers (Ljava/lang/Boolean;)V
2470+
public final fun setShmSize (Ljava/lang/Integer;)V
2471+
public final fun setSquash (Ljava/lang/Boolean;)V
2472+
public final fun setSuppressVerbose (Ljava/lang/Boolean;)V
2473+
public final fun setTag (Ljava/lang/String;)V
2474+
public final fun setTarget (Ljava/lang/String;)V
2475+
public final fun setVersion (Ljava/lang/String;)V
2476+
public fun toString ()Ljava/lang/String;
2477+
}
2478+
23542479
public final class me/devnatan/yoki/models/image/ImageKt {
23552480
public static final fun getCreated (Lme/devnatan/yoki/models/image/Image;)Lkotlinx/datetime/Instant;
23562481
}
@@ -3915,6 +4040,7 @@ public final class me/devnatan/yoki/resource/image/ImageNotFoundException : me/d
39154040

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

4053+
public final class me/devnatan/yoki/resource/image/ImageResourceKt {
4054+
public static final fun build (Lme/devnatan/yoki/resource/image/ImageResource;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
4055+
}
4056+
39274057
public final class me/devnatan/yoki/resource/network/NetworkResource {
39284058
public static final field BASE_PATH Ljava/lang/String;
39294059
public final fun connectContainer (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package me.devnatan.yoki.models
2+
3+
import kotlinx.serialization.Serializable
4+
5+
/**
6+
* Configuration for Docker registry authentication.
7+
*
8+
* @property username The username for authentication with the Docker registry.
9+
* @property password The password for authentication with the Docker registry.
10+
*/
11+
@Serializable
12+
public data class RegistryConfig(val username: String, val password: String)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package me.devnatan.yoki.models.image
2+
3+
import me.devnatan.yoki.models.RegistryConfig
4+
5+
/**
6+
* Options for building a Docker image.
7+
*
8+
* @property path The path to the build context.
9+
* @property tag The tag to be applied to the built image.
10+
* @property extraHosts Additional hosts to add to /etc/hosts in the build containers.
11+
* @property remote URL of the Docker daemon to connect to.
12+
* @property suppressVerbose Suppress verbose output during build.
13+
* @property noCache Do not use the cache when building the image.
14+
* @property cacheFrom List of images used for cache resolution.
15+
* @property pull Always attempt to pull a newer version of the image.
16+
* @property removeIntermediateContainers Remove intermediate containers after a successful build.
17+
* @property forceRemoveIntermediateContainers Force removal of intermediate containers.
18+
* @property memoryLimit Memory limit for the build container.
19+
* @property memorySwap Swap limit equal to memory plus swap.
20+
* @property cpuShares CPU shares for the build container.
21+
* @property cpuSetCpus CPUs in which to allow execution.
22+
* @property cpuPeriod CPU period to be used for the build container.
23+
* @property cpuQuota CPU quota to be used for the build container.
24+
* @property buildArgs Build-time variables to set during the build.
25+
* @property shmSize Size of /dev/shm in bytes.
26+
* @property squash Squash newly built layers into a single new layer.
27+
* @property labels User-defined key-value metadata to add to the image.
28+
* @property networkMode Network mode for the build container.
29+
* @property platform Platform in the format os[/arch[/variant]].
30+
* @property target Build only a specific target stage.
31+
* @property outputs Specify the outputs to be built.
32+
* @property version Version of the build options.
33+
* @property registryConfig Docker registry auth configurations for multiple registries that a build may refer to.
34+
*/
35+
public data class ImageBuildOptions(
36+
public var path: String? = null,
37+
public var tag: String? = null,
38+
public var extraHosts: String? = null,
39+
public var remote: String? = null,
40+
public var suppressVerbose: Boolean? = null,
41+
public var noCache: Boolean? = null,
42+
public var cacheFrom: List<String> = emptyList(),
43+
public var pull: String? = null,
44+
public var removeIntermediateContainers: Boolean? = null,
45+
public var forceRemoveIntermediateContainers: Boolean? = null,
46+
public var memoryLimit: Int? = null,
47+
public var memorySwap: Int? = null,
48+
public var cpuShares: Int? = null,
49+
public var cpuSetCpus: String? = null,
50+
public var cpuPeriod: Int? = null,
51+
public var cpuQuota: Int? = null,
52+
public var buildArgs: Map<String, String> = emptyMap(),
53+
public var shmSize: Int? = null,
54+
public var squash: Boolean? = null,
55+
public var labels: Map<String, String> = emptyMap(),
56+
public var networkMode: String? = null,
57+
public var platform: String? = null,
58+
public var target: String? = null,
59+
public var outputs: String? = null,
60+
public var version: String? = null,
61+
public var registryConfig: Map<String, RegistryConfig> = emptyMap(),
62+
)

src/commonMain/kotlin/me/devnatan/yoki/resource/image/ImageResource.kt

+54-2
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,33 @@ import io.ktor.client.HttpClient
44
import io.ktor.client.call.body
55
import io.ktor.client.request.delete
66
import io.ktor.client.request.get
7+
import io.ktor.client.request.header
78
import io.ktor.client.request.parameter
9+
import io.ktor.client.request.post
810
import io.ktor.client.request.preparePost
11+
import io.ktor.client.request.setBody
12+
import io.ktor.http.ContentType
13+
import io.ktor.http.contentType
914
import io.ktor.utils.io.ByteReadChannel
1015
import io.ktor.utils.io.readUTF8Line
1116
import kotlinx.coroutines.flow.Flow
1217
import kotlinx.coroutines.flow.flow
13-
import kotlinx.serialization.decodeFromString
18+
import kotlinx.serialization.encodeToString
1419
import kotlinx.serialization.json.Json
20+
import me.devnatan.yoki.models.image.ImageBuildOptions
1521
import me.devnatan.yoki.models.image.ImagePull
1622
import me.devnatan.yoki.models.image.ImageSummary
1723

24+
private const val BASE_PATH = "/images"
25+
1826
public class ImageResource internal constructor(
1927
private val httpClient: HttpClient,
2028
private val json: Json,
2129
) {
2230

2331
public companion object {
24-
private const val BASE_PATH = "/images"
32+
33+
private val TAR_CONTENT_TYPE = ContentType.parse("application/x-tar")
2534
}
2635

2736
public suspend fun list(): List<ImageSummary> {
@@ -45,4 +54,47 @@ public class ImageResource internal constructor(
4554
parameter("noprune", noprune)
4655
}
4756
}
57+
58+
/**
59+
* builds a Docker image using the specified archive path and [ImageBuildOptions].
60+
*
61+
* @param archivePath The path to the build context archive (e.g., a TAR file) that contains the source code and resources.
62+
* @param options The [ImageBuildOptions] containing the configuration for the image build.
63+
*/
64+
public suspend fun build(archivePath: String, options: ImageBuildOptions) {
65+
httpClient.post("/build") {
66+
contentType(TAR_CONTENT_TYPE)
67+
header("X-Registry-Config", json.encodeToString(options.registryConfig))
68+
parameter("dockerfile", options.path)
69+
parameter("t", options.tag)
70+
parameter("extrahosts", options.extraHosts)
71+
parameter("remote", options.remote)
72+
parameter("q", options.suppressVerbose)
73+
parameter("nocache", options.noCache)
74+
parameter("cachefrom", options.cacheFrom)
75+
parameter("pull", options.pull)
76+
parameter("rm", options.removeIntermediateContainers)
77+
parameter("forcerm", options.forceRemoveIntermediateContainers)
78+
parameter("memory", options.memoryLimit)
79+
parameter("memswap", options.memorySwap)
80+
parameter("cpushares", options.cpuShares)
81+
parameter("cpusetcpus", options.cpuSetCpus)
82+
parameter("cpuperiod", options.cpuPeriod)
83+
parameter("cpuquota", options.cpuQuota)
84+
parameter("buildargs", options.buildArgs)
85+
parameter("shmsize", options.shmSize)
86+
parameter("squash", options.squash)
87+
parameter("labels", options.labels)
88+
parameter("networkmode", options.networkMode)
89+
parameter("platform", options.platform)
90+
parameter("target", options.target)
91+
parameter("outputs", options.outputs)
92+
parameter("version", options.version)
93+
setBody(archivePath)
94+
}
95+
}
96+
}
97+
98+
public suspend inline fun ImageResource.build(archivePath: String, options: ImageBuildOptions.() -> Unit) {
99+
build(archivePath, ImageBuildOptions().apply(options))
48100
}

0 commit comments

Comments
 (0)