diff --git a/CHANGELOG.md b/CHANGELOG.md index 436ec071..e0bbad14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.2.0 (unreleased) + +* Enhanced Java interoperability (#97) +* Implementation of /events to monitor system events in real time (#101) + # 0.1.1 (08-05-2023) * MacOS and Linux native targets are now published to Maven Central as well diff --git a/SUPPORTED_ENDPOINTS.md b/SUPPORTED_ENDPOINTS.md index 8d29d963..6c4a8185 100644 --- a/SUPPORTED_ENDPOINTS.md +++ b/SUPPORTED_ENDPOINTS.md @@ -1,6 +1,6 @@ # Yoki supported Docker API endpoints -Supports 42 of 106 endpoints +Supports 43 of 106 endpoints ### Containers (15/25) * [x] List containers - GET **/containers/json** @@ -130,7 +130,7 @@ Supports 42 of 106 endpoints * [x] Get version - GET **/version** * [x] Ping - GET **/_ping** * [x] Ping - HEAD **/_ping** -* [ ] Monitor events - GET **/events** +* [x] Monitor events - GET **/events** * [ ] Get data usage information - GET **/system/df** ### Distribution (0/1) diff --git a/api/yoki.api b/api/yoki.api index 66eb874b..3afceec3 100644 --- a/api/yoki.api +++ b/api/yoki.api @@ -3034,126 +3034,185 @@ public final class me/devnatan/yoki/models/secret/SecretSpec$Driver$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class me/devnatan/yoki/models/system/SystemEvent { - public static final field BuilderType Ljava/lang/String; - public static final field Companion Lme/devnatan/yoki/models/system/SystemEvent$Companion; - public static final field ConfigType Ljava/lang/String; - public static final field ContainerType Ljava/lang/String; - public static final field DaemonType Ljava/lang/String; - public static final field ImageType Ljava/lang/String; - public static final field LocalScope Ljava/lang/String; - public static final field NetworkType Ljava/lang/String; - public static final field NodeType Ljava/lang/String; - public static final field PluginType Ljava/lang/String; - public static final field SecretType Ljava/lang/String; - public static final field ServiceType Ljava/lang/String; - public static final field SwarmScope Ljava/lang/String; - public static final field VolumeType Ljava/lang/String; - public synthetic fun (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJLkotlinx/serialization/internal/SerializationConstructorMarker;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)V - public final fun component1 ()Ljava/lang/String; +public final class me/devnatan/yoki/models/system/Event { + public static final field Companion Lme/devnatan/yoki/models/system/Event$Companion; + public synthetic fun (ILme/devnatan/yoki/models/system/EventType;Ljava/lang/String;Lme/devnatan/yoki/models/system/EventActor;Lme/devnatan/yoki/models/system/EventScope;JJLkotlinx/serialization/internal/SerializationConstructorMarker;)V + public final fun component1 ()Lme/devnatan/yoki/models/system/EventType; public final fun component2 ()Ljava/lang/String; - public final fun component3 ()Ljava/lang/String; - public final fun component4 ()Ljava/lang/String; + public final fun component3 ()Lme/devnatan/yoki/models/system/EventActor; + public final fun component4 ()Lme/devnatan/yoki/models/system/EventScope; public final fun component5 ()J public final fun component6 ()J - public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)Lme/devnatan/yoki/models/system/SystemEvent; - public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/SystemEvent;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJILjava/lang/Object;)Lme/devnatan/yoki/models/system/SystemEvent; + public final fun copy (Lme/devnatan/yoki/models/system/EventType;Ljava/lang/String;Lme/devnatan/yoki/models/system/EventActor;Lme/devnatan/yoki/models/system/EventScope;JJ)Lme/devnatan/yoki/models/system/Event; + public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/Event;Lme/devnatan/yoki/models/system/EventType;Ljava/lang/String;Lme/devnatan/yoki/models/system/EventActor;Lme/devnatan/yoki/models/system/EventScope;JJILjava/lang/Object;)Lme/devnatan/yoki/models/system/Event; public fun equals (Ljava/lang/Object;)Z public final fun getAction ()Ljava/lang/String; - public final fun getActor ()Ljava/lang/String; - public final fun getScope ()Ljava/lang/String; - public final fun getTime ()J - public final fun getTimeInNanos ()J - public final fun getType ()Ljava/lang/String; + public final fun getActor ()Lme/devnatan/yoki/models/system/EventActor; + public final fun getScope ()Lme/devnatan/yoki/models/system/EventScope; + public final fun getTimeMillis ()J + public final fun getTimeNanos ()J + public final fun getType ()Lme/devnatan/yoki/models/system/EventType; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lme/devnatan/yoki/models/system/SystemEvent;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V + public static final synthetic fun write$Self (Lme/devnatan/yoki/models/system/Event;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } -public final class me/devnatan/yoki/models/system/SystemEvent$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Lme/devnatan/yoki/models/system/SystemEvent$$serializer; +public final class me/devnatan/yoki/models/system/Event$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lme/devnatan/yoki/models/system/Event$$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/system/SystemEvent; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lme/devnatan/yoki/models/system/Event; 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/system/SystemEvent;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lme/devnatan/yoki/models/system/Event;)V public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } -public final class me/devnatan/yoki/models/system/SystemEvent$Actor { - public static final field Companion Lme/devnatan/yoki/models/system/SystemEvent$Actor$Companion; +public final class me/devnatan/yoki/models/system/Event$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class me/devnatan/yoki/models/system/EventAction : java/lang/Enum { + public static final field ATTACH Lme/devnatan/yoki/models/system/EventAction; + public static final field COMMIT Lme/devnatan/yoki/models/system/EventAction; + public static final field COPY Lme/devnatan/yoki/models/system/EventAction; + public static final field CREATE Lme/devnatan/yoki/models/system/EventAction; + public static final field Companion Lme/devnatan/yoki/models/system/EventAction$Companion; + public static final field DAEMON_RELOAD Lme/devnatan/yoki/models/system/EventAction; + public static final field DELETE Lme/devnatan/yoki/models/system/EventAction; + public static final field DESTROY Lme/devnatan/yoki/models/system/EventAction; + public static final field DETACH Lme/devnatan/yoki/models/system/EventAction; + public static final field DIE Lme/devnatan/yoki/models/system/EventAction; + public static final field EXEC_CREATE Lme/devnatan/yoki/models/system/EventAction; + public static final field EXEC_DETACH Lme/devnatan/yoki/models/system/EventAction; + public static final field EXEC_DIE Lme/devnatan/yoki/models/system/EventAction; + public static final field EXEC_START Lme/devnatan/yoki/models/system/EventAction; + public static final field EXPORT Lme/devnatan/yoki/models/system/EventAction; + public static final field HEALTH Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_LOAD Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_PULL Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_PUSH Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_SAVE Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_TAG Lme/devnatan/yoki/models/system/EventAction; + public static final field IMAGE_UNTAG Lme/devnatan/yoki/models/system/EventAction; + public static final field IMPORT Lme/devnatan/yoki/models/system/EventAction; + public static final field KILL Lme/devnatan/yoki/models/system/EventAction; + public static final field NET_CONNECT Lme/devnatan/yoki/models/system/EventAction; + public static final field NET_DISCONNECT Lme/devnatan/yoki/models/system/EventAction; + public static final field OOM Lme/devnatan/yoki/models/system/EventAction; + public static final field PAUSE Lme/devnatan/yoki/models/system/EventAction; + public static final field PRUNE Lme/devnatan/yoki/models/system/EventAction; + public static final field REMOVE Lme/devnatan/yoki/models/system/EventAction; + public static final field RENAME Lme/devnatan/yoki/models/system/EventAction; + public static final field RESIZE Lme/devnatan/yoki/models/system/EventAction; + public static final field RESTART Lme/devnatan/yoki/models/system/EventAction; + public static final field START Lme/devnatan/yoki/models/system/EventAction; + public static final field STOP Lme/devnatan/yoki/models/system/EventAction; + public static final field TOP Lme/devnatan/yoki/models/system/EventAction; + public static final field UNKNOWN Lme/devnatan/yoki/models/system/EventAction; + public static final field UNPAUSE Lme/devnatan/yoki/models/system/EventAction; + public static final field UPDATE Lme/devnatan/yoki/models/system/EventAction; + public static fun valueOf (Ljava/lang/String;)Lme/devnatan/yoki/models/system/EventAction; + public static fun values ()[Lme/devnatan/yoki/models/system/EventAction; +} + +public final class me/devnatan/yoki/models/system/EventAction$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class me/devnatan/yoki/models/system/EventActor { + public static final field Companion Lme/devnatan/yoki/models/system/EventActor$Companion; public synthetic fun (ILjava/lang/String;Ljava/util/Map;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V - public fun (Ljava/lang/String;Ljava/util/Map;)V - public synthetic fun (Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/util/Map; - public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lme/devnatan/yoki/models/system/SystemEvent$Actor; - public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/SystemEvent$Actor;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lme/devnatan/yoki/models/system/SystemEvent$Actor; + public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lme/devnatan/yoki/models/system/EventActor; + public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/EventActor;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lme/devnatan/yoki/models/system/EventActor; public fun equals (Ljava/lang/Object;)Z public final fun getAttributes ()Ljava/util/Map; public final fun getId ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lme/devnatan/yoki/models/system/SystemEvent$Actor;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V + public static final synthetic fun write$Self (Lme/devnatan/yoki/models/system/EventActor;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } -public final class me/devnatan/yoki/models/system/SystemEvent$Actor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Lme/devnatan/yoki/models/system/SystemEvent$Actor$$serializer; +public final class me/devnatan/yoki/models/system/EventActor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lme/devnatan/yoki/models/system/EventActor$$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/system/SystemEvent$Actor; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lme/devnatan/yoki/models/system/EventActor; 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/system/SystemEvent$Actor;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lme/devnatan/yoki/models/system/EventActor;)V public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } -public final class me/devnatan/yoki/models/system/SystemEvent$Actor$Companion { +public final class me/devnatan/yoki/models/system/EventActor$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class me/devnatan/yoki/models/system/SystemEvent$Companion { +public final class me/devnatan/yoki/models/system/EventKt { + public static final fun getTime (Lme/devnatan/yoki/models/system/Event;)Lkotlinx/datetime/Instant; +} + +public final class me/devnatan/yoki/models/system/EventScope : java/lang/Enum { + public static final field Companion Lme/devnatan/yoki/models/system/EventScope$Companion; + public static final field LOCAL Lme/devnatan/yoki/models/system/EventScope; + public static final field SWARM Lme/devnatan/yoki/models/system/EventScope; + public static final field UNKNOWN Lme/devnatan/yoki/models/system/EventScope; + public static fun valueOf (Ljava/lang/String;)Lme/devnatan/yoki/models/system/EventScope; + public static fun values ()[Lme/devnatan/yoki/models/system/EventScope; +} + +public final class me/devnatan/yoki/models/system/EventScope$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class me/devnatan/yoki/models/system/SystemEventsOptions { - public static final field Companion Lme/devnatan/yoki/models/system/SystemEventsOptions$Companion; +public final class me/devnatan/yoki/models/system/EventType : java/lang/Enum { + public static final field BUILDER Lme/devnatan/yoki/models/system/EventType; + public static final field CONFIG Lme/devnatan/yoki/models/system/EventType; + public static final field CONTAINER Lme/devnatan/yoki/models/system/EventType; + public static final field Companion Lme/devnatan/yoki/models/system/EventType$Companion; + public static final field DAEMON Lme/devnatan/yoki/models/system/EventType; + public static final field IMAGE Lme/devnatan/yoki/models/system/EventType; + public static final field NETWORK Lme/devnatan/yoki/models/system/EventType; + public static final field NODE Lme/devnatan/yoki/models/system/EventType; + public static final field PLUGIN Lme/devnatan/yoki/models/system/EventType; + public static final field SECRET Lme/devnatan/yoki/models/system/EventType; + public static final field SERVICE Lme/devnatan/yoki/models/system/EventType; + public static final field UNKNOWN Lme/devnatan/yoki/models/system/EventType; + public static final field VOLUME Lme/devnatan/yoki/models/system/EventType; + public static fun valueOf (Ljava/lang/String;)Lme/devnatan/yoki/models/system/EventType; + public static fun values ()[Lme/devnatan/yoki/models/system/EventType; +} + +public final class me/devnatan/yoki/models/system/EventType$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class me/devnatan/yoki/models/system/MonitorEventsOptions { public fun ()V - public synthetic fun (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun addFilter (Ljava/lang/String;Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; - public final fun component3 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lme/devnatan/yoki/models/system/SystemEventsOptions; - public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/SystemEventsOptions;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lme/devnatan/yoki/models/system/SystemEventsOptions; + public final fun component3 ()Ljava/util/Map; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)Lme/devnatan/yoki/models/system/MonitorEventsOptions; + public static synthetic fun copy$default (Lme/devnatan/yoki/models/system/MonitorEventsOptions;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lme/devnatan/yoki/models/system/MonitorEventsOptions; public fun equals (Ljava/lang/Object;)Z - public final fun getFilters ()Ljava/lang/String; + public final fun filterByType ([Lme/devnatan/yoki/models/system/EventType;)Lme/devnatan/yoki/models/system/MonitorEventsOptions; + public final fun getFilters ()Ljava/util/Map; public final fun getSince ()Ljava/lang/String; public final fun getUntil ()Ljava/lang/String; public fun hashCode ()I - public final fun setFilters (Ljava/lang/String;)V public final fun setSince (Ljava/lang/String;)V public final fun setUntil (Ljava/lang/String;)V public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Lme/devnatan/yoki/models/system/SystemEventsOptions;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } -public final class me/devnatan/yoki/models/system/SystemEventsOptions$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Lme/devnatan/yoki/models/system/SystemEventsOptions$$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/system/SystemEventsOptions; - 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/system/SystemEventsOptions;)V - public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; -} - -public final class me/devnatan/yoki/models/system/SystemEventsOptions$Companion { - public final fun serializer ()Lkotlinx/serialization/KSerializer; +public final class me/devnatan/yoki/models/system/MonitorEventsOptionsKt { + public static final fun setSince (Lme/devnatan/yoki/models/system/MonitorEventsOptions;Lkotlinx/datetime/Instant;)V + public static final fun setUntil (Lme/devnatan/yoki/models/system/MonitorEventsOptions;Lkotlinx/datetime/Instant;)V } public final class me/devnatan/yoki/models/system/SystemPingData { @@ -3766,12 +3825,18 @@ public class me/devnatan/yoki/resource/swarm/SwarmException : me/devnatan/yoki/Y public final class me/devnatan/yoki/resource/system/SystemResource { public static final field PING_ENDPOINT Ljava/lang/String; + public final fun events (Lme/devnatan/yoki/models/system/MonitorEventsOptions;)Lkotlinx/coroutines/flow/Flow; + public static synthetic fun events$default (Lme/devnatan/yoki/resource/system/SystemResource;Lme/devnatan/yoki/models/system/MonitorEventsOptions;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; public final fun ping (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun ping (ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun ping$default (Lme/devnatan/yoki/resource/system/SystemResource;ZLkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun version (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } +public final class me/devnatan/yoki/resource/system/SystemResourceKt { + public static final fun events (Lme/devnatan/yoki/resource/system/SystemResource;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; +} + public final class me/devnatan/yoki/resource/volume/VolumeResource { public static final field BASE_PATH Ljava/lang/String; public final fun create (Lme/devnatan/yoki/models/volume/VolumeCreateOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/system/Event.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/system/Event.kt new file mode 100644 index 00000000..14b4e4e2 --- /dev/null +++ b/src/commonMain/kotlin/me/devnatan/yoki/models/system/Event.kt @@ -0,0 +1,185 @@ +package me.devnatan.yoki.models.system + +import kotlinx.datetime.Instant +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +public data class Event internal constructor( + @SerialName("Type") public val type: EventType, + @SerialName("Action") public val action: String, + @SerialName("Actor") public val actor: EventActor, + @SerialName("scope") public val scope: EventScope, + @SerialName("time") public val timeMillis: Long, + @SerialName("timeNano") public val timeNanos: Long, +) + +public val Event.time: Instant get() = Instant.fromEpochMilliseconds(timeMillis) + +@Serializable +public enum class EventAction { + @SerialName("attach") + ATTACH, + + @SerialName("commit") + COMMIT, + + @SerialName("copy") + COPY, + + @SerialName("create") + CREATE, + + @SerialName("delete") + DELETE, + + @SerialName("destroy") + DESTROY, + + @SerialName("detach") + DETACH, + + @SerialName("die") + DIE, + + @SerialName("exec_create") + EXEC_CREATE, + + @SerialName("exec_detach") + EXEC_DETACH, + + @SerialName("exec_start") + EXEC_START, + + @SerialName("exec_die") + EXEC_DIE, + + @SerialName("import") + IMPORT, + + @SerialName("export") + EXPORT, + + @SerialName("health_status") + HEALTH, + + @SerialName("kill") + KILL, + + @SerialName("oom") + OOM, + + @SerialName("pause") + PAUSE, + + @SerialName("rename") + RENAME, + + @SerialName("resize") + RESIZE, + + @SerialName("restart") + RESTART, + + @SerialName("start") + START, + + @SerialName("stop") + STOP, + + @SerialName("top") + TOP, + + @SerialName("unpause") + UNPAUSE, + + @SerialName("update") + UPDATE, + + @SerialName("prune") + PRUNE, + + @SerialName("remove") + REMOVE, + + @SerialName("load") + IMAGE_LOAD, + + @SerialName("pull") + IMAGE_PULL, + + @SerialName("push") + IMAGE_PUSH, + + @SerialName("save") + IMAGE_SAVE, + + @SerialName("tag") + IMAGE_TAG, + + @SerialName("untag") + IMAGE_UNTAG, + + @SerialName("reload") + DAEMON_RELOAD, + + @SerialName("connect") + NET_CONNECT, + + @SerialName("disconnect") + NET_DISCONNECT, + UNKNOWN, +} + +@Serializable +public enum class EventType { + @SerialName("builder") + BUILDER, + + @SerialName("config") + CONFIG, + + @SerialName("container") + CONTAINER, + + @SerialName("daemon") + DAEMON, + + @SerialName("image") + IMAGE, + + @SerialName("network") + NETWORK, + + @SerialName("node") + NODE, + + @SerialName("plugin") + PLUGIN, + + @SerialName("secret") + SECRET, + + @SerialName("service") + SERVICE, + + @SerialName("volume") + VOLUME, + UNKNOWN, +} + +@Serializable +public data class EventActor internal constructor( + @SerialName("ID") public val id: String, + @SerialName("Attributes") public val attributes: Map = emptyMap(), +) + +@Serializable +public enum class EventScope { + @SerialName("local") + LOCAL, + + @SerialName("swarm") + SWARM, + UNKNOWN, +} diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/system/MonitorEventsOptions.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/system/MonitorEventsOptions.kt new file mode 100644 index 00000000..df9d497b --- /dev/null +++ b/src/commonMain/kotlin/me/devnatan/yoki/models/system/MonitorEventsOptions.kt @@ -0,0 +1,37 @@ +package me.devnatan.yoki.models.system + +import kotlinx.datetime.Instant + +public data class MonitorEventsOptions( + public var since: String? = null, + public var until: String? = null, + public val filters: MutableMap> = mutableMapOf(), +) { + + /** + * Filters event by one or more types. + * + * @param types The event types to filter. + */ + public fun filterByType(vararg types: EventType): MonitorEventsOptions = apply { + types.forEach { type -> addFilter("type", type.name.lowercase()) } + } + + /** + * Adds a new filter to the monitor events. + * + * @param key The filter key. + * @param value The filter value. + */ + public fun addFilter(key: String, value: String) { + filters.getOrPut(key, ::mutableListOf).add(value) + } +} + +public fun MonitorEventsOptions.setSince(since: Instant?) { + this.since = since?.toString() +} + +public fun MonitorEventsOptions.setUntil(until: Instant?) { + this.until = until?.toString() +} diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEvent.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEvent.kt deleted file mode 100644 index 74d26bc1..00000000 --- a/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEvent.kt +++ /dev/null @@ -1,42 +0,0 @@ -package me.devnatan.yoki.models.system - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -public typealias SystemEventType = String -public typealias SystemEventScope = String - -@Serializable -public data class SystemEvent( - @SerialName("Type") public val type: SystemEventType, - @SerialName("Action") public val action: String, - @SerialName("Actor") public val actor: String, - @SerialName("scope") public val scope: String, - @SerialName("time") public val time: Long, - @SerialName("timeNano") public val timeInNanos: Long, -) { - - @Serializable - public data class Actor( - @SerialName("ID") public val id: String, - @SerialName("Attributes") public val attributes: Map = emptyMap(), - ) - - public companion object { - - public const val LocalScope: SystemEventScope = "local" - public const val SwarmScope: SystemEventScope = "swarm" - - public const val BuilderType: SystemEventType = "builder" - public const val ConfigType: SystemEventType = "config" - public const val ContainerType: SystemEventType = "container" - public const val DaemonType: SystemEventType = "daemon" - public const val ImageType: SystemEventType = "image" - public const val NetworkType: SystemEventType = "network" - public const val NodeType: SystemEventType = "node" - public const val PluginType: SystemEventType = "plugin" - public const val SecretType: SystemEventType = "secret" - public const val ServiceType: SystemEventType = "service" - public const val VolumeType: SystemEventType = "volume" - } -} diff --git a/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEventsOptions.kt b/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEventsOptions.kt deleted file mode 100644 index c3074e44..00000000 --- a/src/commonMain/kotlin/me/devnatan/yoki/models/system/SystemEventsOptions.kt +++ /dev/null @@ -1,10 +0,0 @@ -package me.devnatan.yoki.models.system - -import kotlinx.serialization.Serializable - -@Serializable -public data class SystemEventsOptions( - public var since: String? = null, - public var until: String? = null, - public var filters: String? = null, -) diff --git a/src/commonMain/kotlin/me/devnatan/yoki/resource/system/SystemResource.kt b/src/commonMain/kotlin/me/devnatan/yoki/resource/system/SystemResource.kt index b1e79850..50dfd8cb 100644 --- a/src/commonMain/kotlin/me/devnatan/yoki/resource/system/SystemResource.kt +++ b/src/commonMain/kotlin/me/devnatan/yoki/resource/system/SystemResource.kt @@ -4,7 +4,17 @@ import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.get import io.ktor.client.request.head +import io.ktor.client.request.parameter +import io.ktor.client.request.prepareGet +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.encodeToString +import kotlinx.serialization.json.Json import me.devnatan.yoki.io.requestCatching +import me.devnatan.yoki.models.system.Event +import me.devnatan.yoki.models.system.MonitorEventsOptions import me.devnatan.yoki.models.system.SystemPingData import me.devnatan.yoki.models.system.SystemVersion import kotlin.jvm.JvmOverloads @@ -14,6 +24,7 @@ import kotlin.jvm.JvmOverloads */ public class SystemResource internal constructor( private val httpClient: HttpClient, + private val json: Json, ) { private companion object { @@ -57,4 +68,34 @@ public class SystemResource internal constructor( ) } } + + /** + * Monitors events in real-time from the server. + * + * @param options Options to filter the received events. + */ + public fun events(options: MonitorEventsOptions = MonitorEventsOptions()): Flow = flow { + requestCatching { + httpClient.prepareGet("/events") { + parameter("until", options.until) + parameter("since", options.since) + parameter("filters", json.encodeToString(options.filters)) + }.execute { response -> + val channel = response.body() + while (true) { + val raw = channel.readUTF8Line() ?: break + val decoded = json.decodeFromString(raw) + emit(decoded) + } + } + } + } } + +/** + * Monitors events in real-time from the server. + * + * @param options Options to filter the received events. + */ +public inline fun SystemResource.events(options: MonitorEventsOptions.() -> Unit): Flow = + events(MonitorEventsOptions().apply(options)) diff --git a/src/jvmMain/kotlin/me/devnatan/yoki/Yoki.jvm.kt b/src/jvmMain/kotlin/me/devnatan/yoki/Yoki.jvm.kt index bbb620aa..e05c33e2 100644 --- a/src/jvmMain/kotlin/me/devnatan/yoki/Yoki.jvm.kt +++ b/src/jvmMain/kotlin/me/devnatan/yoki/Yoki.jvm.kt @@ -43,7 +43,7 @@ public actual class Yoki public actual constructor(public actual val config: Yok public actual val secrets: SecretResource = SecretResource(httpClient, json) @get:JvmName("system") - public actual val system: SystemResource = SystemResource(httpClient) + public actual val system: SystemResource = SystemResource(httpClient, json) public actual fun close() { cancel() diff --git a/src/nativeMain/kotlin/me/devnatan/yoki/Yoki.native.kt b/src/nativeMain/kotlin/me/devnatan/yoki/Yoki.native.kt index 150360e1..f72b878a 100644 --- a/src/nativeMain/kotlin/me/devnatan/yoki/Yoki.native.kt +++ b/src/nativeMain/kotlin/me/devnatan/yoki/Yoki.native.kt @@ -28,7 +28,7 @@ public actual class Yoki public actual constructor(public actual val config: Yok public actual val networks: NetworkResource = NetworkResource(httpClient, json) public actual val volumes: VolumeResource = VolumeResource(httpClient, json) public actual val secrets: SecretResource = SecretResource(httpClient, json) - public actual val system: SystemResource = SystemResource(httpClient) + public actual val system: SystemResource = SystemResource(httpClient, json) actual override fun close() { cancel()