diff --git a/api/yoki.api b/api/yoki.api index 717a7691..65f439d2 100644 --- a/api/yoki.api +++ b/api/yoki.api @@ -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 ()V public fun (Lme/devnatan/yoki/YokiConfig;)V @@ -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 (ILjava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun (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 ()V @@ -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 ()V + public fun (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 (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; } @@ -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; @@ -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; diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/RegistryConfig.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/RegistryConfig.kt new file mode 100644 index 00000000..7609f948 --- /dev/null +++ b/src/commonMain/kotlin/me/devnatan/yoki/models/RegistryConfig.kt @@ -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) diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/image/ImageBuildOptions.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/image/ImageBuildOptions.kt new file mode 100644 index 00000000..c09031e9 --- /dev/null +++ b/src/commonMain/kotlin/me/devnatan/yoki/models/image/ImageBuildOptions.kt @@ -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 = 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 = emptyMap(), + public var shmSize: Int? = null, + public var squash: Boolean? = null, + public var labels: Map = 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 = emptyMap(), +) diff --git a/src/commonMain/kotlin/me/devnatan/yoki/resource/image/ImageResource.kt b/src/commonMain/kotlin/me/devnatan/yoki/resource/image/ImageResource.kt index 5d90833c..23f8b98e 100644 --- a/src/commonMain/kotlin/me/devnatan/yoki/resource/image/ImageResource.kt +++ b/src/commonMain/kotlin/me/devnatan/yoki/resource/image/ImageResource.kt @@ -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 { @@ -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)) }