snapctl 0.49.2__tar.gz → 0.49.4__tar.gz

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.

Potentially problematic release.


This version of snapctl might be problematic. Click here for more details.

Files changed (41) hide show
  1. {snapctl-0.49.2 → snapctl-0.49.4}/PKG-INFO +7 -2
  2. {snapctl-0.49.2 → snapctl-0.49.4}/README.md +6 -1
  3. {snapctl-0.49.2 → snapctl-0.49.4}/pyproject.toml +1 -1
  4. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/byows.py +137 -72
  5. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/config/constants.py +3 -1
  6. snapctl-0.49.4/snapctl/data/releases/beta-0.49.3.mdx +7 -0
  7. snapctl-0.49.4/snapctl/data/releases/beta-0.49.4.mdx +8 -0
  8. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/main.py +3 -1
  9. {snapctl-0.49.2 → snapctl-0.49.4}/LICENSE +0 -0
  10. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/__init__.py +0 -0
  11. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/__main__.py +0 -0
  12. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/__init__.py +0 -0
  13. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/byogs.py +0 -0
  14. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/byosnap.py +0 -0
  15. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/game.py +0 -0
  16. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/generate.py +0 -0
  17. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/release_notes.py +0 -0
  18. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/commands/snapend.py +0 -0
  19. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/config/__init__.py +0 -0
  20. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/config/endpoints.py +0 -0
  21. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/config/hashes.py +0 -0
  22. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/__init__.py +0 -0
  23. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/profiles/__init__.py +0 -0
  24. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/profiles/snapser-byosnap-profile.json +0 -0
  25. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/profiles/snapser-byosnap-profile.yaml +0 -0
  26. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/profiles/snapser-byosnap-profile.yml +0 -0
  27. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/__init__.py +0 -0
  28. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.46.0.mdx +0 -0
  29. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.46.4.mdx +0 -0
  30. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.47.0.mdx +0 -0
  31. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.47.1.mdx +0 -0
  32. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.47.2.mdx +0 -0
  33. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.48.0.mdx +0 -0
  34. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.49.0.mdx +0 -0
  35. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.49.1.mdx +0 -0
  36. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/data/releases/beta-0.49.2.mdx +0 -0
  37. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/types/__init__.py +0 -0
  38. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/types/definitions.py +0 -0
  39. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/utils/__init__.py +0 -0
  40. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/utils/echo.py +0 -0
  41. {snapctl-0.49.2 → snapctl-0.49.4}/snapctl/utils/helper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: snapctl
3
- Version: 0.49.2
3
+ Version: 0.49.4
4
4
  Summary: Snapser CLI Tool
5
5
  Author: Ajinkya Apte
6
6
  Author-email: aj@snapser.com
@@ -34,10 +34,13 @@ Snapctl will be the best way for game studios to integrate Snapser into their bu
34
34
  1. Renamed SDK type `server` to `api-key` to be consistent with the Snapser Web app.
35
35
 
36
36
  ### Features
37
- 1. Added support for Bring your own Workstation commands.
37
+ 1. Added support for Bring your own Workstation commands. This enables local debugging for your BYOSnaps while clients continue to access your cloud Snapend APIs.
38
38
  ```bash
39
39
  snapctl byows attach --snapend-id $snapend_id --byosnap-id $byosnap_id --http-port $http_port
40
40
  ```
41
+ ```bash
42
+ snapctl byows reset --snapend-id $snapend_id
43
+ ```
41
44
 
42
45
  ## Requirements
43
46
  ### Python 3.X and Pip
@@ -845,4 +848,6 @@ snapctl generate credentials --category "ecr" --out-path $output_path
845
848
  | Error Code | Description |
846
849
  |------------|----------------------------------------------------------|
847
850
  | 95 | Generic byows error |
851
+ | 96 | Byows attach error |
852
+ | 97 | Byows reset error |
848
853
 
@@ -14,10 +14,13 @@ Snapctl will be the best way for game studios to integrate Snapser into their bu
14
14
  1. Renamed SDK type `server` to `api-key` to be consistent with the Snapser Web app.
15
15
 
16
16
  ### Features
17
- 1. Added support for Bring your own Workstation commands.
17
+ 1. Added support for Bring your own Workstation commands. This enables local debugging for your BYOSnaps while clients continue to access your cloud Snapend APIs.
18
18
  ```bash
19
19
  snapctl byows attach --snapend-id $snapend_id --byosnap-id $byosnap_id --http-port $http_port
20
20
  ```
21
+ ```bash
22
+ snapctl byows reset --snapend-id $snapend_id
23
+ ```
21
24
 
22
25
  ## Requirements
23
26
  ### Python 3.X and Pip
@@ -825,3 +828,5 @@ snapctl generate credentials --category "ecr" --out-path $output_path
825
828
  | Error Code | Description |
826
829
  |------------|----------------------------------------------------------|
827
830
  | 95 | Generic byows error |
831
+ | 96 | Byows attach error |
832
+ | 97 | Byows reset error |
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "snapctl"
3
- version = "0.49.2"
3
+ version = "0.49.4"
4
4
  description = "Snapser CLI Tool"
5
5
  authors = ["Ajinkya Apte <aj@snapser.com>"]
6
6
  readme = "README.md"
@@ -6,23 +6,26 @@ import platform
6
6
  import subprocess
7
7
  import shutil
8
8
  import time
9
- import json
10
- from pathlib import Path
9
+ import signal
10
+ import functools
11
+ import sys
11
12
  from typing import Union
12
13
  import threading
13
14
  import requests
14
15
  from requests.exceptions import RequestException, HTTPError
15
16
  from rich.progress import Progress, SpinnerColumn, TextColumn
16
17
  from snapctl.config.constants import SERVER_CALL_TIMEOUT, SNAPCTL_INPUT_ERROR, \
17
- SNAPCTL_BYOWS_GENERIC_ERROR, SNAPCTL_DEPENDENCY_MISSING
18
+ SNAPCTL_BYOWS_GENERIC_ERROR, SNAPCTL_DEPENDENCY_MISSING, \
19
+ SNAPCTL_BYOWS_ATTACH_ERROR, SNAPCTL_BYOWS_RESET_ERROR
18
20
  from snapctl.utils.helper import snapctl_error, snapctl_success, get_dot_snapser_dir
19
21
  from snapctl.utils.echo import info, warning
20
22
 
23
+
21
24
  class Byows:
22
25
  """
23
26
  CLI commands exposed for a Bring your own Workstation
24
27
  """
25
- SUBCOMMANDS = ['attach']
28
+ SUBCOMMANDS = ['attach', 'reset']
26
29
  SSH_FILE = 'id_snapser_byows_attach_ed25519'
27
30
  PORT_FORWARD_TTL = 3600 * 24 * 7
28
31
  BYOWS_ENV_FILE = 'byows_env_setup'
@@ -41,6 +44,7 @@ class Byows:
41
44
  self.byosnap_id: Union[str, None] = byosnap_id
42
45
  self.http_port: Union[int, None] = http_port
43
46
  self.grpc_port: Union[int, None] = grpc_port
47
+ self._ssh_process = None
44
48
  self.validate_input()
45
49
 
46
50
  def validate_input(self) -> None:
@@ -74,9 +78,14 @@ class Byows:
74
78
  snapctl_error(
75
79
  message="Missing Input. One of --http-port=$your_local_server_port or --grpc-port=$your_local_server_port is required.",
76
80
  code=SNAPCTL_INPUT_ERROR)
77
-
81
+ elif self.subcommand == 'reset':
82
+ if self.snapend_id is None or self.snapend_id == '':
83
+ snapctl_error(
84
+ message="Missing Input --snapend-id=$your_snapend_id",
85
+ code=SNAPCTL_INPUT_ERROR)
78
86
 
79
87
  # Static methods
88
+
80
89
  @staticmethod
81
90
  def stream_output(pipe):
82
91
  '''
@@ -90,11 +99,12 @@ class Byows:
90
99
  def _get_export_commands(snap_ids, port):
91
100
  '''
92
101
  Generate export commands for the given snap IDs and port.
102
+ Replace hyphens with underscores in environment variable names.
93
103
  '''
94
104
  env_vars = []
95
105
 
96
106
  for snap_id in snap_ids:
97
- upper_id = snap_id.upper()
107
+ upper_id = snap_id.upper().replace("-", "_")
98
108
  env_vars.append(f"SNAPEND_{upper_id}_GRPC_URL=localhost:{port}")
99
109
  env_vars.append(
100
110
  f"SNAPEND_{upper_id}_HTTP_URL=http://localhost:{port}")
@@ -112,11 +122,12 @@ class Byows:
112
122
  def _generate_env_file(snap_ids, port):
113
123
  '''
114
124
  Generate an environment file with the given snap IDs and port.
125
+ Replace hyphens with underscores in environment variable names.
115
126
  '''
116
127
  env_lines = []
117
128
 
118
129
  for snap_id in snap_ids:
119
- upper_id = snap_id.upper()
130
+ upper_id = snap_id.upper().replace("-", "_")
120
131
  env_lines.append(
121
132
  f"export SNAPEND_{upper_id}_GRPC_URL=localhost:{port}")
122
133
  env_lines.append(
@@ -174,6 +185,58 @@ class Byows:
174
185
  return f"HTTP Error {http_err.response.status_code}: {http_err.response.reason}\nResponse: {response.text.strip()}"
175
186
 
176
187
  # Private methods
188
+ def _terminate_ssh_process(self):
189
+ if hasattr(self, "_ssh_process") and self._ssh_process:
190
+ try:
191
+ self._ssh_process.terminate()
192
+ if self._ssh_process.poll() is None:
193
+ self._ssh_process.wait(timeout=5)
194
+ except subprocess.TimeoutExpired:
195
+ warning("SSH process did not shut down gracefully.")
196
+
197
+ def _cleanup_files(self):
198
+ try:
199
+ dot_snapser_dir = get_dot_snapser_dir()
200
+ id_file = dot_snapser_dir / Byows.SSH_FILE
201
+ pub_file = dot_snapser_dir / f"{Byows.SSH_FILE}.pub"
202
+ if id_file.exists():
203
+ id_file.unlink()
204
+ if pub_file.exists():
205
+ pub_file.unlink()
206
+ except Exception as e:
207
+ warning(f"Cleanup warning: Failed to delete SSH key files – {e}")
208
+
209
+ def _handle_signal(self, signum, frame):
210
+ print(f"\nReceived signal {signum}. Cleaning up...", flush=True)
211
+ self._terminate_ssh_process()
212
+ self._cleanup_files()
213
+ try:
214
+ url = f"{self.base_url}/v1/snapser-api/byows/snapends/" + \
215
+ f"{self.snapend_id}/snaps/{self.byosnap_id}/enabled"
216
+ res = requests.put(
217
+ url, headers={'api-key': self.api_key}, json=False, timeout=SERVER_CALL_TIMEOUT)
218
+ res.raise_for_status()
219
+ info('Forwarding disabled')
220
+ except HTTPError as http_err:
221
+ snapctl_error(
222
+ message=Byows._format_portal_http_error(
223
+ "Unable to disable BYOWs", http_err, res),
224
+ code=SNAPCTL_BYOWS_GENERIC_ERROR
225
+ )
226
+ except RequestException as req_err:
227
+ warning(
228
+ f"Response Status Code: {res.status_code}, Body: {res.text}")
229
+ snapctl_error(
230
+ message=f"Request Exception: Unable to disable BYOWs {req_err}",
231
+ code=SNAPCTL_BYOWS_GENERIC_ERROR
232
+ )
233
+ except Exception as e:
234
+ snapctl_error(
235
+ message=f"Unexpected error occurred: {e}",
236
+ code=SNAPCTL_BYOWS_GENERIC_ERROR
237
+ )
238
+ sys.exit(0)
239
+
177
240
  def _setup_port_forward(
178
241
  self, private_key, public_key, snapend_id, snap_id, port, reverse_port, reverse_grpc_port,
179
242
  incoming_http, incoming_grpc, outgoing_http, snap_ids, ssh_connect_addr) -> bool:
@@ -220,7 +283,7 @@ class Byows:
220
283
  ssh_command = [
221
284
  'ssh',
222
285
  '-q',
223
- '-4', # use IPv4
286
+ '-4', # use IPv4
224
287
  '-o', 'ServerAliveInterval=60',
225
288
  '-o', 'StrictHostKeyChecking=no',
226
289
  '-o', 'UserKnownHostsFile=/dev/null',
@@ -231,12 +294,13 @@ class Byows:
231
294
  '-R', f'{reverse_port}:localhost:{incoming_http}',
232
295
  ]
233
296
  if incoming_grpc:
234
- ssh_command += ['-R', f'{reverse_grpc_port}:localhost:{incoming_grpc}']
297
+ ssh_command += ['-R',
298
+ f'{reverse_grpc_port}:localhost:{incoming_grpc}']
235
299
  ssh_command += [ssh_host]
236
300
 
237
- process = None
301
+ # process = None
238
302
  try:
239
- process = subprocess.Popen(
303
+ self._ssh_process = subprocess.Popen(
240
304
  ssh_command,
241
305
  shell=False,
242
306
  stdout=subprocess.PIPE,
@@ -247,9 +311,9 @@ class Byows:
247
311
  timeout_seconds = 5
248
312
  start_time = time.time()
249
313
  while True:
250
- if process.poll() is not None:
314
+ if self._ssh_process.poll() is not None:
251
315
  # Process exited early — likely an error
252
- stderr_output = process.stderr.read().decode().strip()
316
+ stderr_output = self._ssh_process.stderr.read().decode().strip()
253
317
  if stderr_output:
254
318
  info(f"[SSH Error] {stderr_output}")
255
319
  else:
@@ -263,60 +327,16 @@ class Byows:
263
327
 
264
328
  # Start background thread to stream live stderr
265
329
  threading.Thread(target=Byows.stream_output, args=(
266
- process.stderr,), daemon=True).start()
330
+ self._ssh_process.stderr,), daemon=True).start()
267
331
 
268
332
  # Now block for the full tunnel lifetime
269
- process.wait(timeout=Byows.PORT_FORWARD_TTL)
333
+ self._ssh_process.wait(timeout=Byows.PORT_FORWARD_TTL)
270
334
  except KeyboardInterrupt:
271
- process.terminate()
272
- try:
273
- process.wait(timeout=5)
274
- except subprocess.TimeoutExpired:
275
- warning('SSH process did not shut down gracefully.')
276
-
277
- info('Shutting down port forward...')
278
-
279
- try:
280
- url = f"{self.base_url}/v1/snapser-api/byows/snapends/" + \
281
- f"{self.snapend_id}/snaps/{self.byosnap_id}/enabled"
282
- res = requests.put(
283
- url, headers={'api-key': self.api_key}, json=False, timeout=SERVER_CALL_TIMEOUT)
284
- res.raise_for_status()
285
- info('Forwarding disabled')
286
- except HTTPError as http_err:
287
- snapctl_error(
288
- message=Byows._format_portal_http_error(
289
- "Unable to disable BYOWs", http_err, res),
290
- code=SNAPCTL_BYOWS_GENERIC_ERROR
291
- )
292
- return False
293
- except RequestException as req_err:
294
- warning(
295
- f"Response Status Code: {res.status_code}, Body: {res.text}")
296
- snapctl_error(
297
- message=f"Request Exception: Unable to disable BYOWs {req_err}",
298
- code=SNAPCTL_BYOWS_GENERIC_ERROR
299
- )
300
- return False
301
- except Exception as e:
302
- snapctl_error(
303
- message=f"Unexpected error occurred: {e}",
304
- code=SNAPCTL_BYOWS_GENERIC_ERROR
305
- )
306
- return False
307
-
335
+ self._handle_signal(signal.SIGINT, None)
336
+ return False
308
337
  except Exception as e:
309
338
  print('Error running SSH command:', e)
310
339
  return False
311
- finally:
312
- # Cleanup the SSH key files
313
- # Only remove the files if they exist
314
- try:
315
- id_file.unlink()
316
- pub_file.unlink()
317
- except Exception as e:
318
- warning(
319
- f"Cleanup warning: Failed to delete SSH key files – {e}")
320
340
  return True
321
341
 
322
342
  # Commands
@@ -330,7 +350,8 @@ class Byows:
330
350
  transient=True,
331
351
  )
332
352
  progress.start()
333
- progress.add_task(description='Setting up BYOWs port forward...', total=None)
353
+ progress.add_task(
354
+ description='Setting up BYOWs port forward...', total=None)
334
355
  try:
335
356
  url = f"{self.base_url}/v1/snapser-api/byows/snapends/" + \
336
357
  f"{self.snapend_id}/snaps/{self.byosnap_id}"
@@ -347,7 +368,6 @@ class Byows:
347
368
  res.raise_for_status()
348
369
  response_json = res.json()
349
370
 
350
-
351
371
  if res.ok and 'workstationPort' in response_json and \
352
372
  'workstationReversePort' in response_json and \
353
373
  'snapendId' in response_json and \
@@ -364,6 +384,16 @@ class Byows:
364
384
 
365
385
  progress.stop()
366
386
 
387
+ info('Setting up signal handling')
388
+ # Set up signal handling for cleanup
389
+ signal.signal(signal.SIGINT, functools.partial(
390
+ self._handle_signal))
391
+ signal.signal(signal.SIGTERM, functools.partial(
392
+ self._handle_signal))
393
+ if hasattr(signal, "SIGBREAK"):
394
+ signal.signal(signal.SIGBREAK,
395
+ functools.partial(self._handle_signal))
396
+ # Set up port forward
367
397
  self._setup_port_forward(
368
398
  response_json['proxyPrivateKey'],
369
399
  response_json['proxyPublicKey'],
@@ -382,21 +412,56 @@ class Byows:
382
412
  message='complete', progress=progress)
383
413
  snapctl_error(
384
414
  message='Unable to setup port forward.',
385
- code=SNAPCTL_BYOWS_GENERIC_ERROR, progress=progress)
415
+ code=SNAPCTL_BYOWS_ATTACH_ERROR, progress=progress)
386
416
  except HTTPError as http_err:
387
417
  snapctl_error(
388
418
  message=Byows._format_portal_http_error(
389
419
  "Unable to setup port forward", http_err, res),
390
- code=SNAPCTL_BYOWS_GENERIC_ERROR, progress=progress)
391
- snapctl_error(
392
- message=f"Server Error: Unable to setup port forward {http_err}",
393
- code=SNAPCTL_BYOWS_GENERIC_ERROR, progress=progress)
420
+ code=SNAPCTL_BYOWS_ATTACH_ERROR, progress=progress)
394
421
  except RequestException as e:
395
422
  snapctl_error(
396
423
  message=f"Exception: Unable to setup port forward {e}",
397
- code=SNAPCTL_BYOWS_GENERIC_ERROR, progress=progress)
424
+ code=SNAPCTL_BYOWS_ATTACH_ERROR, progress=progress)
425
+ finally:
426
+ progress.stop()
427
+
428
+ def reset(self) -> bool:
429
+ """
430
+ BYOWs reset
431
+ """
432
+ progress = Progress(
433
+ SpinnerColumn(),
434
+ TextColumn("[progress.description]{task.description}"),
435
+ transient=True,
436
+ )
437
+ progress.start()
438
+ progress.add_task(
439
+ description='Resetting BYOWS for the Snapend...', total=None)
440
+ try:
441
+ url = f"{self.base_url}/v1/snapser-api/byows/snapends/" + \
442
+ f"{self.snapend_id}"
443
+ res = requests.delete(
444
+ url,
445
+ headers={'api-key': self.api_key},
446
+ timeout=SERVER_CALL_TIMEOUT,
447
+ json={
448
+ "snapend_id": self.snapend_id,
449
+ }
450
+ )
451
+ res.raise_for_status()
452
+ if res.ok:
453
+ return snapctl_success(
454
+ message='Reset complete', progress=progress)
455
+ snapctl_error(
456
+ message='Unable to reset BYOWS.',
457
+ code=SNAPCTL_BYOWS_RESET_ERROR, progress=progress)
458
+ except HTTPError as http_err:
459
+ snapctl_error(
460
+ message=f"Server Error: Unable to reset BYOWS {http_err}",
461
+ code=SNAPCTL_BYOWS_RESET_ERROR, progress=progress)
462
+ except RequestException as e:
463
+ snapctl_error(
464
+ message=f"Exception: Unable to reset BYOWS {e}",
465
+ code=SNAPCTL_BYOWS_RESET_ERROR, progress=progress)
398
466
  finally:
399
467
  progress.stop()
400
- snapctl_error(
401
- message='Failed to setup port forward.',
402
- code=SNAPCTL_BYOWS_GENERIC_ERROR, progress=progress)
@@ -3,7 +3,7 @@ Constants used by snapctl
3
3
  """
4
4
  COMPANY_NAME = 'Snapser'
5
5
  VERSION_PREFIX = 'beta-'
6
- VERSION = '0.49.2'
6
+ VERSION = '0.49.4'
7
7
  CONFIG_FILE_MAC = '~/.snapser/config'
8
8
  CONFIG_FILE_WIN = '%homepath%\\.snapser\\config'
9
9
 
@@ -111,3 +111,5 @@ SNAPCTL_GENERATE_CREDENTIALS_ERROR = 81
111
111
 
112
112
  # BYOWs Errors - 95 - 99
113
113
  SNAPCTL_BYOWS_GENERIC_ERROR = 95
114
+ SNAPCTL_BYOWS_ATTACH_ERROR = 96
115
+ SNAPCTL_BYOWS_RESET_ERROR = 97
@@ -0,0 +1,7 @@
1
+ ## beta-0.49.3
2
+ ##### May 13, 2025
3
+
4
+ ### Feature
5
+ #### Bring your own workstation (BYOW)
6
+ - Now supports a new subcommand `snapctl byows reset --snapend-id $snapendId` to reset the BYOW configuration. Useful when you want a clean slate.
7
+
@@ -0,0 +1,8 @@
1
+ ## beta-0.49.4
2
+ ##### May 20, 2025
3
+
4
+ ### Bug Fixes
5
+
6
+ #### Bring your own workstation (BYOW)
7
+ - Environment exports no longer include hyphens in the variable names.
8
+
@@ -110,6 +110,7 @@ def get_base_url(api_key: Union[str, None]) -> str:
110
110
  return END_POINTS['PLAYTEST']
111
111
  return END_POINTS['PROD']
112
112
 
113
+
113
114
  def get_base_snapend_url(api_key: Union[str, None]) -> str:
114
115
  """
115
116
  Returns the base url for snapend based on the api_key
@@ -124,6 +125,7 @@ def get_base_snapend_url(api_key: Union[str, None]) -> str:
124
125
  return GATEWAY_END_POINTS['SANDBOX']
125
126
  return GATEWAY_END_POINTS['LIVE']
126
127
 
128
+
127
129
  def validate_command_context(
128
130
  ctx: typer.Context,
129
131
  ):
@@ -692,7 +694,7 @@ def byows(
692
694
  # attach
693
695
  snapend_id: str = typer.Option(
694
696
  None, "--snapend-id",
695
- help=("(req: attach) Your Snapend Id")
697
+ help=("(req: attach, reset) Your Snapend Id")
696
698
  ),
697
699
  byosnap_id: str = typer.Option(
698
700
  None, "--byosnap-id",
File without changes
File without changes
File without changes
File without changes