daytona 0.217.0 → 0.220.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 234455e03a95507727b6e1ba8ca933aae0e5c53eb406a5fff4bc051f5f5cb5c9
4
- data.tar.gz: bab2f5ee3e382488f213ff032fb8a3f270f25df077558083e3859e865b9b2b95
3
+ metadata.gz: 6c916e09a640a2761766f1a78652af5821f19a1a123e819844372d87651ca7fc
4
+ data.tar.gz: 486825b3ac58633a87e865a51ad51cdfc42f8bcd1a50f336b83cd43f90aa2856
5
5
  SHA512:
6
- metadata.gz: a404264dccacf27a09c4e176e08baa625e55e66af8979622844b948ecc7b3a0ec7bb380caecfaa46eeb4e4b5ccec6782590bb4fc4ab5f34959283f502ba51574
7
- data.tar.gz: 5849c58ff779775f1a017c099c6d104c4ec99774089c9fe8c10904d7b25eb76cb03918a9f10bc7e9f2476d4be5fdf147cd90b7e2c2856c6ca6fd2624adc08ab1
6
+ metadata.gz: 83c22f64c8aaaf2522945b4fdd7ee1ac6f8fd6f96657027f0e445428ec1907cce96f0f112caee3213ac653ad88a8bca701b0447ce6851451438dca5b834b0576
7
+ data.tar.gz: 7db19827791d02beea4c549c6f53aaa85748504056027f5c0636caaf86a87c18f1017e9ce0c761e1f644da3b30a39dc988c3f09691dea14ee138fe1b834c17f6
@@ -50,6 +50,10 @@ module Daytona
50
50
  # @return [Boolean, nil] Whether to block all network access for the Sandbox
51
51
  attr_accessor :network_block_all
52
52
 
53
+ # @return [Boolean, nil] Expose KVM (/dev/kvm) inside the sandbox via nested virtualization.
54
+ # linux-vm snapshots only. Requires the sandbox_kvm feature for the organization.
55
+ attr_accessor :kvm
56
+
53
57
  # @return [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
54
58
  attr_accessor :network_allow_list
55
59
 
@@ -65,6 +69,9 @@ module Daytona
65
69
  # @return [Integer, nil] Time to live in minutes (0 to disable)
66
70
  attr_accessor :ttl_minutes
67
71
 
72
+ # @return [Integer, nil] Minutes to wait for runner assignment before the API auto-destroys the sandbox
73
+ attr_accessor :queue_timeout
74
+
68
75
  # @return [Boolean, nil] Whether the Sandbox should be ephemeral
69
76
  attr_accessor :ephemeral
70
77
 
@@ -95,6 +102,8 @@ module Daytona
95
102
  # @param secrets [Hash<String, String>, nil] Organization Secrets to expose in the Sandbox, as a
96
103
  # mapping of env var name to existing Secret name
97
104
  # @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
105
+ # @param kvm [Boolean, nil] Expose KVM (/dev/kvm) inside the sandbox via nested virtualization.
106
+ # linux-vm snapshots only. Requires the sandbox_kvm feature for the organization.
98
107
  # @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
99
108
  # @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
100
109
  # @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
@@ -104,6 +113,7 @@ module Daytona
104
113
  # sandbox OTel data is sent to this endpoint instead of the default collector and will not be
105
114
  # available in the Daytona analytics API or dashboard.
106
115
  # @param ttl_minutes [Integer, nil] Time to live in minutes (0 to disable)
116
+ # @param queue_timeout [Integer, nil] Minutes to wait for runner assignment before the API auto-destroys the sandbox
107
117
  # @param ephemeral [Boolean, nil] Whether the Sandbox should be ephemeral
108
118
  # @param spot [Boolean, nil] GPU-only. Whether the Sandbox may be instantly terminated to free GPU
109
119
  # capacity for an on-demand GPU Sandbox
@@ -120,9 +130,11 @@ module Daytona
120
130
  auto_archive_interval: nil,
121
131
  auto_delete_interval: nil,
122
132
  ttl_minutes: nil,
133
+ queue_timeout: nil,
123
134
  volumes: nil,
124
135
  secrets: nil,
125
136
  network_block_all: nil,
137
+ kvm: nil,
126
138
  network_allow_list: nil,
127
139
  domain_allow_list: nil,
128
140
  outbound_proxy_url: nil,
@@ -142,9 +154,11 @@ module Daytona
142
154
  @auto_archive_interval = auto_archive_interval
143
155
  @auto_delete_interval = auto_delete_interval
144
156
  @ttl_minutes = ttl_minutes
157
+ @queue_timeout = queue_timeout
145
158
  @volumes = volumes
146
159
  @secrets = secrets
147
160
  @network_block_all = network_block_all
161
+ @kvm = kvm
148
162
  @network_allow_list = network_allow_list
149
163
  @domain_allow_list = domain_allow_list
150
164
  @outbound_proxy_url = outbound_proxy_url
@@ -173,9 +187,11 @@ module Daytona
173
187
  auto_archive_interval:,
174
188
  auto_delete_interval:,
175
189
  ttl_minutes:,
190
+ queue_timeout:,
176
191
  volumes:,
177
192
  secrets:,
178
193
  network_block_all:,
194
+ kvm:,
179
195
  network_allow_list:,
180
196
  domain_allow_list:,
181
197
  outbound_proxy_url:,
@@ -229,10 +245,13 @@ module Daytona
229
245
  # @param auto_archive_interval [Integer, nil] Auto-archive interval in minutes
230
246
  # @param auto_delete_interval [Integer, nil] Auto-delete interval in minutes
231
247
  # @param ttl_minutes [Integer, nil] Time to live in minutes (0 to disable)
248
+ # @param queue_timeout [Integer, nil] Minutes to wait for runner assignment before the API auto-destroys the sandbox
232
249
  # @param volumes [Array<DaytonaApiClient::SandboxVolume>, nil] List of volumes mounts to attach to the Sandbox
233
250
  # @param secrets [Hash<String, String>, nil] Organization Secrets to expose in the Sandbox, as a
234
251
  # mapping of env var name to existing Secret name
235
252
  # @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
253
+ # @param kvm [Boolean, nil] Expose KVM (/dev/kvm) inside the sandbox via nested virtualization.
254
+ # linux-vm snapshots only. Requires the sandbox_kvm feature for the organization.
236
255
  # @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
237
256
  # @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
238
257
  # @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
@@ -278,10 +297,13 @@ module Daytona
278
297
  # @param auto_archive_interval [Integer, nil] Auto-archive interval in minutes
279
298
  # @param auto_delete_interval [Integer, nil] Auto-delete interval in minutes
280
299
  # @param ttl_minutes [Integer, nil] Time to live in minutes (0 to disable)
300
+ # @param queue_timeout [Integer, nil] Minutes to wait for runner assignment before the API auto-destroys the sandbox
281
301
  # @param volumes [Array<DaytonaApiClient::SandboxVolume>, nil] List of volumes mounts to attach to the Sandbox
282
302
  # @param secrets [Hash<String, String>, nil] Organization Secrets to expose in the Sandbox, as a
283
303
  # mapping of env var name to existing Secret name
284
304
  # @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
305
+ # @param kvm [Boolean, nil] Expose KVM (/dev/kvm) inside the sandbox via nested virtualization.
306
+ # linux-vm snapshots only. Requires the sandbox_kvm feature for the organization.
285
307
  # @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
286
308
  # @param domain_allow_list [String, nil] Comma-separated list of allowed domains for the Sandbox
287
309
  # @param outbound_proxy_url [String, nil] Outbound proxy URL to route the Sandbox HTTP(S) traffic through.
@@ -104,7 +104,7 @@ module Daytona
104
104
  # @param params [Daytona::CreateSandboxFromSnapshotParams, Daytona::CreateSandboxFromImageParams, Nil] Sandbox creation parameters
105
105
  # @return [Daytona::Sandbox] The created sandbox
106
106
  # @raise [Daytona::Sdk::Error] If auto_stop_interval, auto_pause_interval, auto_archive_interval, or ttl_minutes is negative,
107
- # or if auto_stop_interval and auto_pause_interval are both non-zero
107
+ # if queue_timeout is not a positive integer, or if auto_stop_interval and auto_pause_interval are both non-zero
108
108
  def create(params = nil, on_snapshot_create_logs: nil)
109
109
  if params.nil?
110
110
  params = CreateSandboxFromSnapshotParams.new(language: CodeLanguage::PYTHON)
@@ -249,7 +249,7 @@ module Daytona
249
249
  # @param on_snapshot_create_logs [Proc]
250
250
  # @return [Daytona::Sandbox] The created sandbox
251
251
  # @raise [Daytona::Sdk::Error] If auto_stop_interval, auto_pause_interval, auto_archive_interval, or ttl_minutes is negative,
252
- # or if auto_stop_interval and auto_pause_interval are both non-zero
252
+ # if queue_timeout is not a positive integer, or if auto_stop_interval and auto_pause_interval are both non-zero
253
253
  def _create(params, timeout: 60, on_snapshot_create_logs: nil)
254
254
  raise Sdk::Error, 'Timeout must be a non-negative number' if timeout.negative?
255
255
 
@@ -274,6 +274,10 @@ module Daytona
274
274
 
275
275
  raise Sdk::Error, 'ttl_minutes must be a non-negative integer' if params.ttl_minutes&.negative?
276
276
 
277
+ unless params.queue_timeout.nil? || (params.queue_timeout.is_a?(Integer) && params.queue_timeout >= 1)
278
+ raise Sdk::Error, 'queue_timeout must be a positive integer'
279
+ end
280
+
277
281
  labels = params.labels&.dup || {}
278
282
  labels[CODE_TOOLBOX_LANGUAGE_LABEL] = params.language.to_s if params.language
279
283
 
@@ -288,9 +292,11 @@ module Daytona
288
292
  auto_archive_interval: params.auto_archive_interval,
289
293
  auto_delete_interval: params.auto_delete_interval,
290
294
  ttl_minutes: params.ttl_minutes,
295
+ queue_timeout: params.queue_timeout,
291
296
  volumes: params.volumes,
292
297
  secrets: params.secrets&.map { |env_var, secret_name| { env_var.to_s => secret_name.to_s } },
293
298
  network_block_all: params.network_block_all,
299
+ kvm: params.kvm,
294
300
  network_allow_list: params.network_allow_list,
295
301
  domain_allow_list: params.domain_allow_list,
296
302
  outbound_proxy_url: params.outbound_proxy_url,
@@ -332,13 +338,23 @@ module Daytona
332
338
  response = sandbox_api.get_sandbox(response.id)
333
339
  end
334
340
 
335
- # Get build logs URL from API
336
- build_logs_response = sandbox_api.get_build_logs_url(response.id)
337
- uri = URI.parse("#{build_logs_response.url}?follow=true")
341
+ begin
342
+ build_logs_response = sandbox_api.get_build_logs_url(response.id)
343
+ uri = URI.parse("#{build_logs_response.url}?follow=true")
344
+
345
+ headers = {}
346
+ sandbox_api.api_client.update_params_for_auth!(headers, nil, ['bearer'])
347
+ Util.stream_async(uri:, headers:, on_chunk: on_snapshot_create_logs)
348
+ rescue StandardError => e
349
+ refreshed = begin
350
+ sandbox_api.get_sandbox(response.id)
351
+ rescue StandardError
352
+ raise e
353
+ end
354
+ raise e unless destroyed_by_lifecycle?(refreshed)
338
355
 
339
- headers = {}
340
- sandbox_api.api_client.update_params_for_auth!(headers, nil, ['bearer'])
341
- Util.stream_async(uri:, headers:, on_chunk: on_snapshot_create_logs)
356
+ response = refreshed
357
+ end
342
358
  end
343
359
 
344
360
  sandbox = to_sandbox(sandbox_dto: response)
@@ -394,6 +410,15 @@ module Daytona
394
410
 
395
411
  # @param sandbox_dto [DaytonaApiClient::Sandbox, DaytonaApiClient::SandboxListItem]
396
412
  # @return [Daytona::Sandbox]
413
+ def destroyed_by_lifecycle?(sandbox_dto)
414
+ if sandbox_dto.state == DaytonaApiClient::SandboxState::DESTROYED &&
415
+ (sandbox_dto.queue_timed_out_at || sandbox_dto.spot_evicted_at)
416
+ true
417
+ else
418
+ false
419
+ end
420
+ end
421
+
397
422
  def to_sandbox(sandbox_dto:)
398
423
  Sandbox.new(
399
424
  sandbox_dto:,
@@ -80,6 +80,10 @@ module Daytona
80
80
  # Not returned by list results; call #refresh on each item to populate.
81
81
  attr_reader :network_block_all
82
82
 
83
+ # @return [Boolean, nil] Whether the sandbox exposes KVM (/dev/kvm) to its guest.
84
+ # Not returned by list results; call #refresh on each item to populate.
85
+ attr_reader :kvm
86
+
83
87
  # @return [String, nil] Comma-separated list of allowed CIDR network addresses for the sandbox.
84
88
  # Not returned by list results; call #refresh on each item to populate.
85
89
  attr_reader :network_allow_list
@@ -112,6 +116,9 @@ module Daytona
112
116
  # @return [String, nil] When the sandbox was evicted by spot preemption
113
117
  attr_reader :spot_evicted_at
114
118
 
119
+ # @return [String, nil] When the sandbox timed out waiting in the queue for a runner
120
+ attr_reader :queue_timed_out_at
121
+
115
122
  # @return [String, nil] The GPU type assigned to the sandbox
116
123
  attr_reader :gpu_type
117
124
 
@@ -162,6 +169,9 @@ module Daytona
162
169
  # @return [String, nil] When the sandbox will be automatically destroyed (nil if no TTL is set)
163
170
  attr_reader :auto_destroy_at
164
171
 
172
+ # @return [Integer, nil] Minutes the sandbox may wait for runner assignment before the API auto-destroys it
173
+ attr_reader :queue_timeout
174
+
165
175
  # @return [String] The creation timestamp of the sandbox
166
176
  attr_reader :created_at
167
177
 
@@ -1107,6 +1117,7 @@ module Daytona
1107
1117
  @gpu = sandbox_dto.gpu
1108
1118
  @spot = sandbox_dto.spot || false
1109
1119
  @spot_evicted_at = sandbox_dto.spot_evicted_at
1120
+ @queue_timed_out_at = sandbox_dto.queue_timed_out_at
1110
1121
  @gpu_type = sandbox_dto.gpu_type
1111
1122
  @memory = sandbox_dto.memory
1112
1123
  @disk = sandbox_dto.disk
@@ -1118,6 +1129,7 @@ module Daytona
1118
1129
  @auto_archive_interval = sandbox_dto.auto_archive_interval
1119
1130
  @auto_delete_interval = sandbox_dto.auto_delete_interval
1120
1131
  @auto_destroy_at = sandbox_dto.auto_destroy_at
1132
+ @queue_timeout = sandbox_dto.queue_timeout
1121
1133
  @created_at = sandbox_dto.created_at
1122
1134
  @updated_at = sandbox_dto.updated_at
1123
1135
  @last_activity_at = sandbox_dto.last_activity_at
@@ -1136,6 +1148,7 @@ module Daytona
1136
1148
  if sandbox_dto.is_a?(DaytonaApiClient::Sandbox)
1137
1149
  @env = sandbox_dto.env
1138
1150
  @network_block_all = sandbox_dto.network_block_all
1151
+ @kvm = sandbox_dto.kvm
1139
1152
  @network_allow_list = sandbox_dto.network_allow_list
1140
1153
  @domain_allow_list = sandbox_dto.domain_allow_list
1141
1154
  @outbound_proxy_url = sandbox_dto.outbound_proxy_url
@@ -1240,6 +1253,7 @@ module Daytona
1240
1253
  first_poll = false
1241
1254
 
1242
1255
  safe_refresh ? refresh_data_safe : refresh
1256
+ raise_destroyed_lifecycle_error_if_needed(target_strings)
1243
1257
 
1244
1258
  mutex.synchronize do
1245
1259
  next if result_state
@@ -1265,6 +1279,8 @@ module Daytona
1265
1279
  rescue StandardError
1266
1280
  raise e
1267
1281
  end
1282
+
1283
+ raise_destroyed_lifecycle_error_if_needed(target_strings)
1268
1284
  current = state.to_s
1269
1285
  return if target_strings.include?(current)
1270
1286
 
@@ -1288,6 +1304,26 @@ module Daytona
1288
1304
  rescue StandardError # rubocop:disable Lint/SuppressedException
1289
1305
  end
1290
1306
 
1307
+ def raise_destroyed_lifecycle_error_if_needed(target_strings)
1308
+ return unless state.to_s == DaytonaApiClient::SandboxState::DESTROYED.to_s
1309
+ return if target_strings.include?(DaytonaApiClient::SandboxState::DESTROYED.to_s)
1310
+
1311
+ raise Sdk::QueueTimeoutError, queue_timeout_message if queue_timed_out_at
1312
+ return unless spot_evicted_at
1313
+
1314
+ raise Sdk::SpotEvictedError,
1315
+ "Sandbox #{id} was evicted by spot preemption at #{spot_evicted_at}"
1316
+ end
1317
+
1318
+ def queue_timeout_message
1319
+ waited = if queue_timeout.nil?
1320
+ ''
1321
+ else
1322
+ " #{queue_timeout} #{queue_timeout == 1 ? 'minute' : 'minutes'}"
1323
+ end
1324
+ "Sandbox #{id} was destroyed after waiting#{waited} for a runner (queue timed out at #{queue_timed_out_at})"
1325
+ end
1326
+
1291
1327
  def ensure_subscribed
1292
1328
  @waiter_mutex.synchronize do
1293
1329
  return unless @subscription_manager
@@ -107,6 +107,17 @@ module Daytona
107
107
  # catch the broader connection-failure category also match.
108
108
  class ConnectionTimeoutError < ConnectionError; end
109
109
 
110
+ # ---------------------------------------------------------------------
111
+ # SDK-detected sandbox lifecycle
112
+ # ---------------------------------------------------------------------
113
+
114
+ # Raised when a Sandbox was destroyed by the API because it waited longer
115
+ # than its queue timeout for a runner.
116
+ class QueueTimeoutError < TimeoutError; end
117
+
118
+ # Raised when a Sandbox was destroyed by spot preemption.
119
+ class SpotEvictedError < Error; end
120
+
110
121
  # ---------------------------------------------------------------------
111
122
  # Domain subclasses — each inherits from the HTTP-status parent that
112
123
  # matches its server-side status code.
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Daytona
7
7
  module Sdk
8
- VERSION = '0.217.0'
8
+ VERSION = '0.220.0'
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daytona
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.217.0
4
+ version: 0.220.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daytona Platforms Inc.
@@ -91,42 +91,42 @@ dependencies:
91
91
  requirements:
92
92
  - - '='
93
93
  - !ruby/object:Gem::Version
94
- version: 0.217.0
94
+ version: 0.220.0
95
95
  type: :runtime
96
96
  prerelease: false
97
97
  version_requirements: !ruby/object:Gem::Requirement
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 0.217.0
101
+ version: 0.220.0
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: daytona_api_client
104
104
  requirement: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - '='
107
107
  - !ruby/object:Gem::Version
108
- version: 0.217.0
108
+ version: 0.220.0
109
109
  type: :runtime
110
110
  prerelease: false
111
111
  version_requirements: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - '='
114
114
  - !ruby/object:Gem::Version
115
- version: 0.217.0
115
+ version: 0.220.0
116
116
  - !ruby/object:Gem::Dependency
117
117
  name: daytona_toolbox_api_client
118
118
  requirement: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - '='
121
121
  - !ruby/object:Gem::Version
122
- version: 0.217.0
122
+ version: 0.220.0
123
123
  type: :runtime
124
124
  prerelease: false
125
125
  version_requirements: !ruby/object:Gem::Requirement
126
126
  requirements:
127
127
  - - '='
128
128
  - !ruby/object:Gem::Version
129
- version: 0.217.0
129
+ version: 0.220.0
130
130
  - !ruby/object:Gem::Dependency
131
131
  name: dotenv
132
132
  requirement: !ruby/object:Gem::Requirement