unitlab 2.3.8__py3-none-any.whl → 2.3.10__py3-none-any.whl

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.
unitlab/client.py CHANGED
@@ -297,10 +297,10 @@ class UnitlabClient:
297
297
  self.tunnel_manager = CloudflareTunnel(base_domain, device_id)
298
298
  self.jupyter_url = self.tunnel_manager.jupyter_url
299
299
  self.ssh_url = self.tunnel_manager.ssh_url
300
- else:
301
- self.tunnel_manager = None
302
- self.jupyter_url = f"https://jupyter-{device_id}.{base_domain}"
303
- self.ssh_url = f"https://ssh-{device_id}.{base_domain}"
300
+ else:
301
+ self.tunnel_manager = None
302
+ self.jupyter_url = f"https://jupyter-{device_id}.{base_domain}"
303
+ self.ssh_url = f"https://ssh-{device_id}.{base_domain}"
304
304
 
305
305
  # Setup signal handlers
306
306
  signal.signal(signal.SIGINT, self._handle_shutdown)
@@ -53,16 +53,24 @@ class CloudflareAPITunnel:
53
53
  "Content-Type": "application/json"
54
54
  } if self.api_token else {}
55
55
 
56
- # URLs for services
56
+ # URLs for services - simplified for Jupyter only
57
57
  self.jupyter_subdomain = f"j{self.clean_device_id}"
58
- self.ssh_subdomain = f"s{self.clean_device_id}"
59
58
  self.jupyter_url = f"https://{self.jupyter_subdomain}.{self.base_domain}"
59
+
60
+ # Keep SSH URLs for compatibility but they won't work yet
61
+ self.ssh_subdomain = f"s{self.clean_device_id}"
60
62
  self.ssh_hostname = f"{self.ssh_subdomain}.{self.base_domain}"
61
- self.ssh_url = self.ssh_hostname # For backward compatibility
63
+ self.ssh_url = self.ssh_hostname
62
64
 
63
65
  self.tunnel_process = None
64
66
  self.created_dns_records = []
65
- self.binary_manager = CloudflaredBinaryManager()
67
+
68
+ # Try to initialize binary manager, but don't fail if it doesn't work
69
+ try:
70
+ self.binary_manager = CloudflaredBinaryManager()
71
+ except Exception as e:
72
+ logger.warning(f"Binary manager initialization failed: {e}")
73
+ self.binary_manager = None
66
74
 
67
75
  def create_dns_records(self):
68
76
  """
@@ -209,14 +217,15 @@ class CloudflareAPITunnel:
209
217
  self.create_dns_records()
210
218
  self.update_tunnel_config()
211
219
 
212
- # Get cloudflared binary
213
- cloudflared_path = self.binary_manager.get_binary_path()
220
+ # Ensure cloudflared is available
221
+ cloudflared_path = self._ensure_cloudflared()
222
+ if not cloudflared_path:
223
+ raise RuntimeError("Failed to obtain cloudflared binary")
214
224
 
215
- # Use the service token - hardcoded for zero-config experience
216
- # This token can ONLY run the tunnel, cannot modify or delete it (safe to embed)
217
- service_token = "eyJhIjoiYzkxMTkyYWUyMGE1ZDQzZjY1ZTA4NzU1MGQ4ZGM4OWIiLCJ0IjoiMDc3N2ZjMTAtNDljNC00NzJkLTg2NjEtZjYwZDgwZDYxODRkIiwicyI6Ik9XRTNaak5tTVdVdE1tWTRaUzAwTmpoakxUazBaalF0WXpjek1tSm1ZVGt4WlRRMCJ9"
225
+ # Use service token - simple and reliable
226
+ # The dashboard must have *.1scan.uz -> localhost:8888 configured
227
+ service_token = "eyJhIjoiYzkxMTkyYWUyMGE1ZDQzZjY1ZTA4NzU1MGQ4ZGM4OWIiLCJ0IjoiMDc3N2ZjMTAtNDljNC00NzJkLTg2NjEtZjYwZDgwZDYxODRkIiwicyI6Ik9XRTNaak5tTVdVdE1tWTRaUzAwTmpoakxTazBaalF0WXpjek1tSm1ZVGt4WlRRMCJ9"
218
228
 
219
- # Start tunnel with service token
220
229
  cmd = [
221
230
  cloudflared_path,
222
231
  "tunnel",
@@ -269,6 +278,74 @@ class CloudflareAPITunnel:
269
278
  self.tunnel_process.wait(timeout=5)
270
279
  print("Tunnel stopped")
271
280
 
281
+ def _ensure_cloudflared(self):
282
+ """
283
+ Ensure cloudflared binary is available
284
+ Downloads it if necessary
285
+ """
286
+ print("🔍 Checking for cloudflared binary...")
287
+
288
+ # Try binary manager first
289
+ if self.binary_manager:
290
+ try:
291
+ path = self.binary_manager.get_binary_path()
292
+ print(f"✅ Using cloudflared from binary manager: {path}")
293
+ return path
294
+ except Exception as e:
295
+ logger.warning(f"Binary manager failed, will download directly: {e}")
296
+
297
+ # Direct download fallback - simplified version
298
+ import platform
299
+ import urllib.request
300
+
301
+ cache_dir = Path.home() / '.unitlab' / 'bin'
302
+ cache_dir.mkdir(parents=True, exist_ok=True)
303
+
304
+ cloudflared_path = cache_dir / 'cloudflared'
305
+ if platform.system() == 'Windows':
306
+ cloudflared_path = cache_dir / 'cloudflared.exe'
307
+
308
+ # If already exists, use it
309
+ if cloudflared_path.exists():
310
+ print(f"✅ Using cached cloudflared: {cloudflared_path}")
311
+ return str(cloudflared_path)
312
+
313
+ # Download based on platform
314
+ system = platform.system().lower()
315
+ machine = platform.machine().lower()
316
+
317
+ print(f"📥 Downloading cloudflared for {system}/{machine}...")
318
+
319
+ if system == 'linux':
320
+ if machine in ['x86_64', 'amd64']:
321
+ url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64'
322
+ elif machine in ['aarch64', 'arm64']:
323
+ url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64'
324
+ else:
325
+ url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-386'
326
+ elif system == 'darwin':
327
+ url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tgz'
328
+ elif system == 'windows':
329
+ url = 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe'
330
+ else:
331
+ raise RuntimeError(f"Unsupported platform: {system}")
332
+
333
+ try:
334
+ # Download the file
335
+ urllib.request.urlretrieve(url, cloudflared_path)
336
+
337
+ # Make executable on Unix
338
+ if system != 'windows':
339
+ import stat
340
+ cloudflared_path.chmod(cloudflared_path.stat().st_mode | stat.S_IEXEC)
341
+
342
+ print(f"✅ Downloaded cloudflared to: {cloudflared_path}")
343
+ return str(cloudflared_path)
344
+
345
+ except Exception as e:
346
+ print(f"❌ Failed to download cloudflared: {e}")
347
+ raise RuntimeError(f"Could not download cloudflared: {e}")
348
+
272
349
  def cleanup_dns(self):
273
350
  """
274
351
  Remove created DNS records (optional cleanup)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unitlab
3
- Version: 2.3.8
3
+ Version: 2.3.10
4
4
  Home-page: https://github.com/teamunitlab/unitlab-sdk
5
5
  Author: Unitlab Inc.
6
6
  Author-email: team@unitlab.ai
@@ -0,0 +1,16 @@
1
+ unitlab/__init__.py,sha256=Wtk5kQ_MTlxtd3mxJIn2qHVK5URrVcasMMPjD3BtrVM,214
2
+ unitlab/__main__.py,sha256=6Hs2PV7EYc5Tid4g4OtcLXhqVHiNYTGzSBdoOnW2HXA,29
3
+ unitlab/binary_manager.py,sha256=bZmT07K2InCrZp1KYXgLntEqnQxPFLqPBDf-LcG25Yo,4544
4
+ unitlab/client.py,sha256=nA2jeRNWu_Devq841rTt8tSFwHr9y9oJ2GZnPL6GTog,24343
5
+ unitlab/cloudflare_api_tunnel.py,sha256=ccFAVXXVFLTmIzgVFgCRFyReHrjipGLt00k-0nnCmHM,14481
6
+ unitlab/exceptions.py,sha256=68Tr6LreEzjQ3Vns8HAaWdtewtkNUJOvPazbf6NSnXU,950
7
+ unitlab/main.py,sha256=h1WG6up6STt-2fJZAkqnxenwJ7kmkqnkfq5Zs4xLSeI,5257
8
+ unitlab/tunnel_config.py,sha256=7CiAqasfg26YQfJYXapCBQPSoqw4jIx6yR64saybLLo,8312
9
+ unitlab/tunnel_service_token.py,sha256=ji96a4s4W2cFJrHZle0zBD85Ac_T862-gCKzBUomrxM,3125
10
+ unitlab/utils.py,sha256=83ekAxxfXecFTg76Z62BGDybC_skKJHYoLyawCD9wGM,1920
11
+ unitlab-2.3.10.dist-info/LICENSE.md,sha256=Gn7RRvByorAcAaM-WbyUpsgi5ED1-bKFFshbWfYYz2Y,1069
12
+ unitlab-2.3.10.dist-info/METADATA,sha256=EvIeQay7u1oL5jUyaD3p2ivNXC_BsRnwmvTrHO4xqIk,844
13
+ unitlab-2.3.10.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
14
+ unitlab-2.3.10.dist-info/entry_points.txt,sha256=ig-PjKEqSCj3UTdyANgEi4tsAU84DyXdaOJ02NHX4bY,45
15
+ unitlab-2.3.10.dist-info/top_level.txt,sha256=Al4ZlTYE3fTJK2o6YLCDMH5_DjuQkffRBMxgmWbKaqQ,8
16
+ unitlab-2.3.10.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- unitlab/__init__.py,sha256=Wtk5kQ_MTlxtd3mxJIn2qHVK5URrVcasMMPjD3BtrVM,214
2
- unitlab/__main__.py,sha256=6Hs2PV7EYc5Tid4g4OtcLXhqVHiNYTGzSBdoOnW2HXA,29
3
- unitlab/binary_manager.py,sha256=bZmT07K2InCrZp1KYXgLntEqnQxPFLqPBDf-LcG25Yo,4544
4
- unitlab/client.py,sha256=ejH6FzNawsVAKOMeHXZX4eboP_b2JyR6BlvUdx2lQYw,24327
5
- unitlab/cloudflare_api_tunnel.py,sha256=Bvxohwe0PFTGKmAht1eWbKIlMmADCbB3zqocxqx9D8s,11242
6
- unitlab/exceptions.py,sha256=68Tr6LreEzjQ3Vns8HAaWdtewtkNUJOvPazbf6NSnXU,950
7
- unitlab/main.py,sha256=h1WG6up6STt-2fJZAkqnxenwJ7kmkqnkfq5Zs4xLSeI,5257
8
- unitlab/tunnel_config.py,sha256=7CiAqasfg26YQfJYXapCBQPSoqw4jIx6yR64saybLLo,8312
9
- unitlab/tunnel_service_token.py,sha256=ji96a4s4W2cFJrHZle0zBD85Ac_T862-gCKzBUomrxM,3125
10
- unitlab/utils.py,sha256=83ekAxxfXecFTg76Z62BGDybC_skKJHYoLyawCD9wGM,1920
11
- unitlab-2.3.8.dist-info/LICENSE.md,sha256=Gn7RRvByorAcAaM-WbyUpsgi5ED1-bKFFshbWfYYz2Y,1069
12
- unitlab-2.3.8.dist-info/METADATA,sha256=3qkLQKkMUunI7FYOn8F-MFEnmLCbHQZLd3_dPcwwb3I,843
13
- unitlab-2.3.8.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
14
- unitlab-2.3.8.dist-info/entry_points.txt,sha256=ig-PjKEqSCj3UTdyANgEi4tsAU84DyXdaOJ02NHX4bY,45
15
- unitlab-2.3.8.dist-info/top_level.txt,sha256=Al4ZlTYE3fTJK2o6YLCDMH5_DjuQkffRBMxgmWbKaqQ,8
16
- unitlab-2.3.8.dist-info/RECORD,,