daytona 0.203.0 → 0.205.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/daytona/common/daytona.rb +40 -0
- data/lib/daytona/common/snapshot.rb +18 -0
- data/lib/daytona/daytona.rb +8 -1
- data/lib/daytona/sandbox.rb +14 -0
- data/lib/daytona/sdk/errors.rb +4 -0
- data/lib/daytona/sdk/version.rb +1 -1
- data/lib/daytona/sdk.rb +2 -0
- data/lib/daytona/snapshot_service.rb +43 -9
- data/lib/daytona/warm_pool.rb +75 -0
- data/lib/daytona/warm_pool_service.rb +61 -0
- data/project.json +1 -1
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba9a97a7af09b8d505de9b5d107a764c5e150e21c5b336bd732f5ff8d98341cb
|
|
4
|
+
data.tar.gz: 22057c0b0bd750faa8403fed0b52716ff423d0223cbfc8059935a412bc127f2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e66d5b8c8a2b3e11468840705f4bbc8c199ece6639047c9cbab4e0c69981740a413f474ea1a18b3162963e5c599aced27878f963899b4f890094f51000baa885
|
|
7
|
+
data.tar.gz: 888b3b55cdaded8230e1662816eb4b8bea4541737025da1796d997cd619d1438b6108d138a6e09f19fe0956e37d6c3a2ff47bf5ea55289184c97d703ea18a252
|
|
@@ -56,12 +56,23 @@ module Daytona
|
|
|
56
56
|
# @return [String, nil] Comma-separated list of allowed domains for the Sandbox
|
|
57
57
|
attr_accessor :domain_allow_list
|
|
58
58
|
|
|
59
|
+
# @return [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through
|
|
60
|
+
attr_accessor :outbound_proxy_url
|
|
61
|
+
|
|
62
|
+
# @return [String, nil] OTel collector endpoint override for the Sandbox
|
|
63
|
+
attr_accessor :otel_endpoint_override
|
|
64
|
+
|
|
59
65
|
# @return [Integer, nil] Time to live in minutes (0 to disable)
|
|
60
66
|
attr_accessor :ttl_minutes
|
|
61
67
|
|
|
62
68
|
# @return [Boolean, nil] Whether the Sandbox should be ephemeral
|
|
63
69
|
attr_accessor :ephemeral
|
|
64
70
|
|
|
71
|
+
# @return [Boolean, nil] GPU-only. When true, the Sandbox may be instantly terminated without notice
|
|
72
|
+
# to free GPU capacity for an on-demand (non-spot) GPU Sandbox. Rejected when the Sandbox
|
|
73
|
+
# requests no GPUs.
|
|
74
|
+
attr_accessor :spot
|
|
75
|
+
|
|
65
76
|
# @return [String, nil] ID or name of an existing Sandbox to link the new Sandbox to. The new
|
|
66
77
|
# Sandbox will be scheduled on the same runner as the linked Sandbox so a local network can be
|
|
67
78
|
# established between them. Linked Sandboxes must be
|
|
@@ -86,8 +97,16 @@ module Daytona
|
|
|
86
97
|
# @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
|
|
87
98
|
# @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
|
|
88
99
|
# @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
|
|
100
|
+
# @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
|
|
101
|
+
# Applied via the HTTP(S)_PROXY environment variables; combine with domain_allow_list for
|
|
102
|
+
# network-layer enforcement.
|
|
103
|
+
# @param otel_endpoint_override [String, nil] OTel collector endpoint override for the Sandbox. When set,
|
|
104
|
+
# sandbox OTel data is sent to this endpoint instead of the default collector and will not be
|
|
105
|
+
# available in the Daytona analytics API or dashboard.
|
|
89
106
|
# @param ttl_minutes [Integer, nil] Time to live in minutes (0 to disable)
|
|
90
107
|
# @param ephemeral [Boolean, nil] Whether the Sandbox should be ephemeral
|
|
108
|
+
# @param spot [Boolean, nil] GPU-only. Whether the Sandbox may be instantly terminated to free GPU
|
|
109
|
+
# capacity for an on-demand GPU Sandbox
|
|
91
110
|
# @param linked_sandbox [String, nil] ID or name of an existing Sandbox to link the new Sandbox to
|
|
92
111
|
def initialize( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
|
|
93
112
|
language: nil,
|
|
@@ -106,7 +125,10 @@ module Daytona
|
|
|
106
125
|
network_block_all: nil,
|
|
107
126
|
network_allow_list: nil,
|
|
108
127
|
domain_allow_list: nil,
|
|
128
|
+
outbound_proxy_url: nil,
|
|
129
|
+
otel_endpoint_override: nil,
|
|
109
130
|
ephemeral: nil,
|
|
131
|
+
spot: nil,
|
|
110
132
|
linked_sandbox: nil
|
|
111
133
|
)
|
|
112
134
|
@language = language
|
|
@@ -125,7 +147,10 @@ module Daytona
|
|
|
125
147
|
@network_block_all = network_block_all
|
|
126
148
|
@network_allow_list = network_allow_list
|
|
127
149
|
@domain_allow_list = domain_allow_list
|
|
150
|
+
@outbound_proxy_url = outbound_proxy_url
|
|
151
|
+
@otel_endpoint_override = otel_endpoint_override
|
|
128
152
|
@ephemeral = ephemeral
|
|
153
|
+
@spot = spot
|
|
129
154
|
@linked_sandbox = linked_sandbox
|
|
130
155
|
|
|
131
156
|
# Handle ephemeral and auto_delete_interval conflict
|
|
@@ -153,7 +178,10 @@ module Daytona
|
|
|
153
178
|
network_block_all:,
|
|
154
179
|
network_allow_list:,
|
|
155
180
|
domain_allow_list:,
|
|
181
|
+
outbound_proxy_url:,
|
|
182
|
+
otel_endpoint_override:,
|
|
156
183
|
ephemeral:,
|
|
184
|
+
spot:,
|
|
157
185
|
linked_sandbox:
|
|
158
186
|
}.compact
|
|
159
187
|
end
|
|
@@ -207,6 +235,12 @@ module Daytona
|
|
|
207
235
|
# @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
|
|
208
236
|
# @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
|
|
209
237
|
# @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
|
|
238
|
+
# @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
|
|
239
|
+
# Applied via the HTTP(S)_PROXY environment variables; combine with domain_allow_list for
|
|
240
|
+
# network-layer enforcement.
|
|
241
|
+
# @param otel_endpoint_override [String, nil] OTel collector endpoint override for the Sandbox. When set,
|
|
242
|
+
# sandbox OTel data is sent to this endpoint instead of the default collector and will not be
|
|
243
|
+
# available in the Daytona analytics API or dashboard.
|
|
210
244
|
# @param ephemeral [Boolean, nil] Whether the Sandbox should be ephemeral
|
|
211
245
|
def initialize(image:, resources: nil, **args)
|
|
212
246
|
@image = image
|
|
@@ -250,6 +284,12 @@ module Daytona
|
|
|
250
284
|
# @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
|
|
251
285
|
# @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
|
|
252
286
|
# @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
|
|
287
|
+
# @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
|
|
288
|
+
# Applied via the HTTP(S)_PROXY environment variables; combine with domain_allow_list for
|
|
289
|
+
# network-layer enforcement.
|
|
290
|
+
# @param otel_endpoint_override [String, nil] OTel collector endpoint override for the Sandbox. When set,
|
|
291
|
+
# sandbox OTel data is sent to this endpoint instead of the default collector and will not be
|
|
292
|
+
# available in the Daytona analytics API or dashboard.
|
|
253
293
|
# @param ephemeral [Boolean, nil] Whether the Sandbox should be ephemeral
|
|
254
294
|
def initialize(snapshot: nil, **args)
|
|
255
295
|
@snapshot = snapshot
|
|
@@ -43,6 +43,14 @@ module Daytona
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
class Snapshot
|
|
46
|
+
# Matches RFC 4122 UUIDs (versions 1-5) and the nil UUID - the same set the
|
|
47
|
+
# Daytona API recognizes as snapshot IDs. Anything else is treated as a name.
|
|
48
|
+
SNAPSHOT_ID_PATTERN = Regexp.new(
|
|
49
|
+
'\A(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}' \
|
|
50
|
+
'|00000000-0000-0000-0000-000000000000)\z',
|
|
51
|
+
Regexp::IGNORECASE
|
|
52
|
+
).freeze
|
|
53
|
+
|
|
46
54
|
# @return [String] Unique identifier for the Snapshot
|
|
47
55
|
attr_reader :id
|
|
48
56
|
|
|
@@ -94,6 +102,9 @@ module Daytona
|
|
|
94
102
|
# @return [DaytonaApiClient::BuildInfo, nil] Build information for the snapshot
|
|
95
103
|
attr_reader :build_info
|
|
96
104
|
|
|
105
|
+
# @return [String, nil] ID of the sandbox the Snapshot was created from
|
|
106
|
+
attr_reader :source_sandbox_id
|
|
107
|
+
|
|
97
108
|
# @param snapshot_dto [DaytonaApiClient::SnapshotDto] The snapshot DTO from the API
|
|
98
109
|
def initialize(snapshot_dto) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
99
110
|
@id = snapshot_dto.id
|
|
@@ -113,6 +124,7 @@ module Daytona
|
|
|
113
124
|
@updated_at = snapshot_dto.updated_at
|
|
114
125
|
@last_used_at = snapshot_dto.last_used_at
|
|
115
126
|
@build_info = snapshot_dto.build_info
|
|
127
|
+
@source_sandbox_id = snapshot_dto.source_sandbox_id
|
|
116
128
|
end
|
|
117
129
|
|
|
118
130
|
# Creates a Snapshot instance from a SnapshotDto
|
|
@@ -120,5 +132,11 @@ module Daytona
|
|
|
120
132
|
# @param dto [DaytonaApiClient::SnapshotDto] The snapshot DTO from the API
|
|
121
133
|
# @return [Daytona::Snapshot] The snapshot instance
|
|
122
134
|
def self.from_dto(dto) = new(dto)
|
|
135
|
+
|
|
136
|
+
# Whether the given value looks like a Snapshot ID (a UUID) rather than a name.
|
|
137
|
+
#
|
|
138
|
+
# @param value [Object] value to test
|
|
139
|
+
# @return [Boolean] true when value is a UUID-shaped String
|
|
140
|
+
def self.id?(value) = value.is_a?(String) && SNAPSHOT_ID_PATTERN.match?(value)
|
|
123
141
|
end
|
|
124
142
|
end
|
data/lib/daytona/daytona.rb
CHANGED
|
@@ -25,6 +25,9 @@ module Daytona
|
|
|
25
25
|
# @return [Daytona::SecretService]
|
|
26
26
|
attr_reader :secret
|
|
27
27
|
|
|
28
|
+
# @return [Daytona::WarmPoolService]
|
|
29
|
+
attr_reader :warm_pool
|
|
30
|
+
|
|
28
31
|
# @return [DaytonaApiClient::ObjectStorageApi]
|
|
29
32
|
attr_reader :object_storage_api
|
|
30
33
|
|
|
@@ -53,6 +56,7 @@ module Daytona
|
|
|
53
56
|
@analytics_api_url_mutex = Mutex.new
|
|
54
57
|
@volume = VolumeService.new(DaytonaApiClient::VolumesApi.new(api_client), otel_state:)
|
|
55
58
|
@secret = SecretService.new(DaytonaApiClient::SecretApi.new(api_client), otel_state:)
|
|
59
|
+
@warm_pool = WarmPoolService.new(DaytonaApiClient::WarmPoolsApi.new(api_client), otel_state:)
|
|
56
60
|
@object_storage_api = DaytonaApiClient::ObjectStorageApi.new(api_client)
|
|
57
61
|
@snapshots_api = DaytonaApiClient::SnapshotsApi.new(api_client)
|
|
58
62
|
@snapshot = SnapshotService.new(
|
|
@@ -289,7 +293,10 @@ module Daytona
|
|
|
289
293
|
network_block_all: params.network_block_all,
|
|
290
294
|
network_allow_list: params.network_allow_list,
|
|
291
295
|
domain_allow_list: params.domain_allow_list,
|
|
292
|
-
|
|
296
|
+
outbound_proxy_url: params.outbound_proxy_url,
|
|
297
|
+
otel_endpoint_override: params.otel_endpoint_override,
|
|
298
|
+
linked_sandbox: params.linked_sandbox,
|
|
299
|
+
spot: params.spot
|
|
293
300
|
)
|
|
294
301
|
|
|
295
302
|
create_sandbox.snapshot = params.snapshot if params.respond_to?(:snapshot)
|
data/lib/daytona/sandbox.rb
CHANGED
|
@@ -88,6 +88,10 @@ module Daytona
|
|
|
88
88
|
# Not returned by list results; call #refresh on each item to populate.
|
|
89
89
|
attr_reader :domain_allow_list
|
|
90
90
|
|
|
91
|
+
# @return [String, nil] Outbound proxy URL to route the sandbox HTTP(S) traffic through.
|
|
92
|
+
# Not returned by list results; call #refresh on each item to populate.
|
|
93
|
+
attr_reader :outbound_proxy_url
|
|
94
|
+
|
|
91
95
|
# @return [String] The target environment for the sandbox
|
|
92
96
|
attr_reader :target
|
|
93
97
|
|
|
@@ -97,6 +101,13 @@ module Daytona
|
|
|
97
101
|
# @return [Float] The GPU quota for the sandbox
|
|
98
102
|
attr_reader :gpu
|
|
99
103
|
|
|
104
|
+
# @return [Boolean] Whether this is a spot GPU sandbox. Spot sandboxes may be instantly terminated
|
|
105
|
+
# to free capacity for on-demand GPU sandboxes.
|
|
106
|
+
attr_reader :spot
|
|
107
|
+
|
|
108
|
+
# @return [String, nil] When the sandbox was evicted by spot preemption
|
|
109
|
+
attr_reader :spot_evicted_at
|
|
110
|
+
|
|
100
111
|
# @return [Float] The memory quota for the sandbox
|
|
101
112
|
attr_reader :memory
|
|
102
113
|
|
|
@@ -1081,6 +1092,8 @@ module Daytona
|
|
|
1081
1092
|
@target = sandbox_dto.target
|
|
1082
1093
|
@cpu = sandbox_dto.cpu
|
|
1083
1094
|
@gpu = sandbox_dto.gpu
|
|
1095
|
+
@spot = sandbox_dto.spot || false
|
|
1096
|
+
@spot_evicted_at = sandbox_dto.spot_evicted_at
|
|
1084
1097
|
@memory = sandbox_dto.memory
|
|
1085
1098
|
@disk = sandbox_dto.disk
|
|
1086
1099
|
@desired_state = sandbox_dto.desired_state
|
|
@@ -1109,6 +1122,7 @@ module Daytona
|
|
|
1109
1122
|
@network_block_all = sandbox_dto.network_block_all
|
|
1110
1123
|
@network_allow_list = sandbox_dto.network_allow_list
|
|
1111
1124
|
@domain_allow_list = sandbox_dto.domain_allow_list
|
|
1125
|
+
@outbound_proxy_url = sandbox_dto.outbound_proxy_url
|
|
1112
1126
|
@volumes = sandbox_dto.volumes
|
|
1113
1127
|
@build_info = sandbox_dto.build_info
|
|
1114
1128
|
@backup_created_at = sandbox_dto.backup_created_at
|
data/lib/daytona/sdk/errors.rb
CHANGED
|
@@ -120,6 +120,8 @@ module Daytona
|
|
|
120
120
|
class GitPushRejectedError < ConflictError; end
|
|
121
121
|
class GitDirtyWorktreeError < ConflictError; end
|
|
122
122
|
class GitMergeConflictError < ConflictError; end
|
|
123
|
+
class GitTransportFailedError < BadGatewayError; end
|
|
124
|
+
class GitRemoteRejectedError < UnprocessableEntityError; end
|
|
123
125
|
|
|
124
126
|
# Daemon: filesystem
|
|
125
127
|
class FileNotFoundError < NotFoundError; end
|
|
@@ -177,6 +179,8 @@ module Daytona
|
|
|
177
179
|
[SOURCE_DAEMON, 'GIT_PUSH_REJECTED'] => GitPushRejectedError,
|
|
178
180
|
[SOURCE_DAEMON, 'GIT_DIRTY_WORKTREE'] => GitDirtyWorktreeError,
|
|
179
181
|
[SOURCE_DAEMON, 'GIT_MERGE_CONFLICT'] => GitMergeConflictError,
|
|
182
|
+
[SOURCE_DAEMON, 'GIT_TRANSPORT_FAILED'] => GitTransportFailedError,
|
|
183
|
+
[SOURCE_DAEMON, 'GIT_REMOTE_REJECTED'] => GitRemoteRejectedError,
|
|
180
184
|
|
|
181
185
|
# Daemon: filesystem
|
|
182
186
|
[SOURCE_DAEMON, 'FILE_NOT_FOUND'] => FileNotFoundError,
|
data/lib/daytona/sdk/version.rb
CHANGED
data/lib/daytona/sdk.rb
CHANGED
|
@@ -26,6 +26,7 @@ module Daytona
|
|
|
26
26
|
#
|
|
27
27
|
# @param page [Integer, Nil]
|
|
28
28
|
# @param limit [Integer, Nil]
|
|
29
|
+
# @param source_sandbox_id [String, Nil] Filter by the ID of the sandbox the snapshot was created from
|
|
29
30
|
# @return [Daytona::PaginatedResource] Paginated list of all Snapshots
|
|
30
31
|
# @raise [Daytona::Sdk::Error]
|
|
31
32
|
#
|
|
@@ -34,12 +35,12 @@ module Daytona
|
|
|
34
35
|
# page = daytona.snapshot.list(page: 2, limit: 10)
|
|
35
36
|
# puts "Page #{page.page} of #{page.total_pages} (#{page.total} snapshots total)"
|
|
36
37
|
# page.items.each { |snapshot| puts "#{snapshot.name} (#{snapshot.image_name})" }
|
|
37
|
-
def list(page: nil, limit: nil)
|
|
38
|
+
def list(page: nil, limit: nil, source_sandbox_id: nil)
|
|
38
39
|
raise Sdk::Error, 'page must be positive integer' if page && page < 1
|
|
39
40
|
|
|
40
41
|
raise Sdk::Error, 'limit must be positive integer' if limit && limit < 1
|
|
41
42
|
|
|
42
|
-
response = snapshots_api.get_all_snapshots(page:, limit:)
|
|
43
|
+
response = snapshots_api.get_all_snapshots(page:, limit:, source_sandbox_id:)
|
|
43
44
|
PaginatedResource.new(
|
|
44
45
|
total: response.total,
|
|
45
46
|
page: response.page,
|
|
@@ -50,7 +51,10 @@ module Daytona
|
|
|
50
51
|
|
|
51
52
|
# Delete a Snapshot.
|
|
52
53
|
#
|
|
53
|
-
# @param snapshot [Daytona::Snapshot] Snapshot to delete
|
|
54
|
+
# @param snapshot [Daytona::Snapshot, String] Snapshot to delete, or its ID or name.
|
|
55
|
+
# Call cost: 1 API call for a Snapshot object or UUID string; 2 for a name
|
|
56
|
+
# (resolve, then delete); up to 3 in the worst case for a UUID-formatted name
|
|
57
|
+
# (the optimistic delete 404s, then resolve + delete).
|
|
54
58
|
# @return [void]
|
|
55
59
|
#
|
|
56
60
|
# @example
|
|
@@ -58,11 +62,13 @@ module Daytona
|
|
|
58
62
|
# snapshot = daytona.snapshot.get("demo")
|
|
59
63
|
# daytona.snapshot.delete(snapshot)
|
|
60
64
|
# puts "Snapshot deleted"
|
|
61
|
-
def delete(snapshot)
|
|
65
|
+
def delete(snapshot)
|
|
66
|
+
call_with_resolved_id(snapshot) { |id| snapshots_api.remove_snapshot(id) }
|
|
67
|
+
end
|
|
62
68
|
|
|
63
|
-
# Get a Snapshot by name.
|
|
69
|
+
# Get a Snapshot by ID or name.
|
|
64
70
|
#
|
|
65
|
-
# @param name [String]
|
|
71
|
+
# @param name [String] ID or name of the Snapshot to get
|
|
66
72
|
# @return [Daytona::Snapshot] The Snapshot object
|
|
67
73
|
#
|
|
68
74
|
# @example
|
|
@@ -126,11 +132,15 @@ module Daytona
|
|
|
126
132
|
Snapshot.from_dto(snapshot)
|
|
127
133
|
end
|
|
128
134
|
|
|
129
|
-
# Activate a snapshot
|
|
135
|
+
# Activate a snapshot.
|
|
130
136
|
#
|
|
131
|
-
# @param snapshot [Daytona::Snapshot] The
|
|
137
|
+
# @param snapshot [Daytona::Snapshot, String] The Snapshot instance, or its ID or name.
|
|
138
|
+
# Call cost matches `delete`: 1 for an object or UUID string, 2 for a name,
|
|
139
|
+
# up to 3 for a UUID-formatted name (optimistic 404 then resolve + activate).
|
|
132
140
|
# @return [Daytona::Snapshot]
|
|
133
|
-
def activate(snapshot)
|
|
141
|
+
def activate(snapshot)
|
|
142
|
+
Snapshot.from_dto(call_with_resolved_id(snapshot) { |id| snapshots_api.activate_snapshot(id) })
|
|
143
|
+
end
|
|
134
144
|
|
|
135
145
|
instrument :list, :delete, :get, :create, :activate, component: 'SnapshotService'
|
|
136
146
|
|
|
@@ -175,6 +185,30 @@ module Daytona
|
|
|
175
185
|
# @return [Daytona::OtelState, nil]
|
|
176
186
|
attr_reader :otel_state
|
|
177
187
|
|
|
188
|
+
# Invoke an ID-based Snapshot operation, resolving the given identifier with as
|
|
189
|
+
# few API calls as possible. Snapshot names may themselves be UUID-formatted, so
|
|
190
|
+
# a UUID-shaped string is first tried directly as an ID (single call) and only
|
|
191
|
+
# resolved through the API on a 404. Any other string costs one resolution call.
|
|
192
|
+
#
|
|
193
|
+
# @param snapshot [Daytona::Snapshot, String] Snapshot instance, ID, or name
|
|
194
|
+
# @yield [String] resolved Snapshot ID
|
|
195
|
+
# @yieldreturn [Object] operation result
|
|
196
|
+
# @return [Object] whatever the block returns
|
|
197
|
+
def call_with_resolved_id(snapshot)
|
|
198
|
+
return yield(snapshot.id) unless snapshot.is_a?(String)
|
|
199
|
+
|
|
200
|
+
if Snapshot.id?(snapshot)
|
|
201
|
+
begin
|
|
202
|
+
return yield(snapshot)
|
|
203
|
+
rescue DaytonaApiClient::ApiError => e
|
|
204
|
+
raise unless e.code == 404
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
resolved = snapshots_api.get_snapshot(snapshot)
|
|
209
|
+
yield(resolved.id)
|
|
210
|
+
end
|
|
211
|
+
|
|
178
212
|
# Wait for snapshot to reach a terminal state (ACTIVE, ERROR, or BUILD_FAILED)
|
|
179
213
|
# Optionally streams logs if on_logs callback is provided
|
|
180
214
|
#
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Copyright Daytona Platforms Inc.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
module Daytona
|
|
7
|
+
# A warm pool of ready-to-use Sandboxes for a snapshot. `current_size` versus
|
|
8
|
+
# `pool` is the pool's status: `current_size` is the number of ready warm
|
|
9
|
+
# sandboxes, `pool` is the desired number. `error_reason` is set when the
|
|
10
|
+
# pool cannot be filled.
|
|
11
|
+
class WarmPool
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :id
|
|
14
|
+
|
|
15
|
+
# @return [String]
|
|
16
|
+
attr_reader :organization_id
|
|
17
|
+
|
|
18
|
+
# @return [String]
|
|
19
|
+
attr_reader :snapshot
|
|
20
|
+
|
|
21
|
+
# @return [String]
|
|
22
|
+
attr_reader :target
|
|
23
|
+
|
|
24
|
+
# @return [Integer]
|
|
25
|
+
attr_reader :pool
|
|
26
|
+
|
|
27
|
+
# @return [Integer]
|
|
28
|
+
attr_reader :current_size
|
|
29
|
+
|
|
30
|
+
# @return [Integer]
|
|
31
|
+
attr_reader :cpu
|
|
32
|
+
|
|
33
|
+
# @return [Integer]
|
|
34
|
+
attr_reader :mem
|
|
35
|
+
|
|
36
|
+
# @return [Integer]
|
|
37
|
+
attr_reader :disk
|
|
38
|
+
|
|
39
|
+
# @return [String]
|
|
40
|
+
attr_reader :os_user
|
|
41
|
+
|
|
42
|
+
# @return [Hash{String => String}]
|
|
43
|
+
attr_reader :env
|
|
44
|
+
|
|
45
|
+
# @return [String, nil]
|
|
46
|
+
attr_reader :error_reason
|
|
47
|
+
|
|
48
|
+
# @return [String]
|
|
49
|
+
attr_reader :created_at
|
|
50
|
+
|
|
51
|
+
# @return [String]
|
|
52
|
+
attr_reader :updated_at
|
|
53
|
+
|
|
54
|
+
# Initialize warm pool from DTO
|
|
55
|
+
#
|
|
56
|
+
# @param warm_pool_dto [DaytonaApiClient::WarmPool]
|
|
57
|
+
def initialize(warm_pool_dto)
|
|
58
|
+
@id = warm_pool_dto.id
|
|
59
|
+
@organization_id = warm_pool_dto.organization_id
|
|
60
|
+
@snapshot = warm_pool_dto.snapshot
|
|
61
|
+
@target = warm_pool_dto.target
|
|
62
|
+
# The generated client deserializes OpenAPI numbers as Float; these are all integral.
|
|
63
|
+
@pool = warm_pool_dto.pool.to_i
|
|
64
|
+
@current_size = warm_pool_dto.current_size.to_i
|
|
65
|
+
@cpu = warm_pool_dto.cpu.to_i
|
|
66
|
+
@mem = warm_pool_dto.mem.to_i
|
|
67
|
+
@disk = warm_pool_dto.disk.to_i
|
|
68
|
+
@os_user = warm_pool_dto.os_user
|
|
69
|
+
@env = warm_pool_dto.env
|
|
70
|
+
@error_reason = warm_pool_dto.error_reason
|
|
71
|
+
@created_at = warm_pool_dto.created_at
|
|
72
|
+
@updated_at = warm_pool_dto.updated_at
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Copyright Daytona Platforms Inc.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
module Daytona
|
|
7
|
+
class WarmPoolService
|
|
8
|
+
include Instrumentation
|
|
9
|
+
|
|
10
|
+
# Service for managing Daytona Warm Pools. Can be used to list, create, update and delete Warm Pools.
|
|
11
|
+
#
|
|
12
|
+
# @param warm_pools_api [DaytonaApiClient::WarmPoolsApi]
|
|
13
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
14
|
+
def initialize(warm_pools_api, otel_state: nil)
|
|
15
|
+
@warm_pools_api = warm_pools_api
|
|
16
|
+
@otel_state = otel_state
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Create a new Warm Pool.
|
|
20
|
+
#
|
|
21
|
+
# @param snapshot [String] The snapshot (ID or name) to keep warm sandboxes for
|
|
22
|
+
# @param pool [Integer] Number of warm sandboxes to keep ready
|
|
23
|
+
# @param target [String, nil] Target region; defaults to the organization default region
|
|
24
|
+
# @return [Daytona::WarmPool]
|
|
25
|
+
def create(snapshot, pool, target: nil)
|
|
26
|
+
WarmPool.new(warm_pools_api.create_warm_pool(DaytonaApiClient::CreateWarmPool.new(snapshot:, pool:, target:)))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Delete a Warm Pool.
|
|
30
|
+
#
|
|
31
|
+
# @param warm_pool_id [String]
|
|
32
|
+
# @return [void]
|
|
33
|
+
def delete(warm_pool_id) = warm_pools_api.delete_warm_pool(warm_pool_id)
|
|
34
|
+
|
|
35
|
+
# List all Warm Pools.
|
|
36
|
+
#
|
|
37
|
+
# @return [Array<Daytona::WarmPool>]
|
|
38
|
+
def list
|
|
39
|
+
warm_pools_api.list_warm_pools.map { |warm_pool| WarmPool.new(warm_pool) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Update the desired size of a Warm Pool.
|
|
43
|
+
#
|
|
44
|
+
# @param warm_pool_id [String]
|
|
45
|
+
# @param pool [Integer] New desired number of warm sandboxes (0 drains the pool)
|
|
46
|
+
# @return [Daytona::WarmPool]
|
|
47
|
+
def update(warm_pool_id, pool)
|
|
48
|
+
WarmPool.new(warm_pools_api.update_warm_pool(warm_pool_id, DaytonaApiClient::UpdateWarmPool.new(pool:)))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
instrument :create, :delete, :list, :update, component: 'WarmPoolService'
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# @return [DaytonaApiClient::WarmPoolsApi]
|
|
56
|
+
attr_reader :warm_pools_api
|
|
57
|
+
|
|
58
|
+
# @return [Daytona::OtelState, nil]
|
|
59
|
+
attr_reader :otel_state
|
|
60
|
+
end
|
|
61
|
+
end
|
data/project.json
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: daytona
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.205.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daytona Platforms Inc.
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 1980-01-
|
|
10
|
+
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: opentelemetry-exporter-otlp
|
|
@@ -85,42 +85,42 @@ dependencies:
|
|
|
85
85
|
requirements:
|
|
86
86
|
- - '='
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: 0.
|
|
88
|
+
version: 0.205.0
|
|
89
89
|
type: :runtime
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
93
|
- - '='
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: 0.
|
|
95
|
+
version: 0.205.0
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: daytona_api_client
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
|
100
100
|
- - '='
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: 0.
|
|
102
|
+
version: 0.205.0
|
|
103
103
|
type: :runtime
|
|
104
104
|
prerelease: false
|
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
|
107
107
|
- - '='
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
|
-
version: 0.
|
|
109
|
+
version: 0.205.0
|
|
110
110
|
- !ruby/object:Gem::Dependency
|
|
111
111
|
name: daytona_toolbox_api_client
|
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
|
113
113
|
requirements:
|
|
114
114
|
- - '='
|
|
115
115
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: 0.
|
|
116
|
+
version: 0.205.0
|
|
117
117
|
type: :runtime
|
|
118
118
|
prerelease: false
|
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
120
120
|
requirements:
|
|
121
121
|
- - '='
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: 0.
|
|
123
|
+
version: 0.205.0
|
|
124
124
|
- !ruby/object:Gem::Dependency
|
|
125
125
|
name: dotenv
|
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -238,6 +238,8 @@ files:
|
|
|
238
238
|
- lib/daytona/utils/file_url_signing.rb
|
|
239
239
|
- lib/daytona/volume.rb
|
|
240
240
|
- lib/daytona/volume_service.rb
|
|
241
|
+
- lib/daytona/warm_pool.rb
|
|
242
|
+
- lib/daytona/warm_pool_service.rb
|
|
241
243
|
- project.json
|
|
242
244
|
- scripts/generate-docs.rb
|
|
243
245
|
- sig/daytona/sdk.rbs
|
|
@@ -264,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
264
266
|
- !ruby/object:Gem::Version
|
|
265
267
|
version: '0'
|
|
266
268
|
requirements: []
|
|
267
|
-
rubygems_version: 3.
|
|
269
|
+
rubygems_version: 3.7.2
|
|
268
270
|
specification_version: 4
|
|
269
271
|
summary: Ruby SDK for Daytona
|
|
270
272
|
test_files: []
|