autoverse-cli 0.28.3__tar.gz → 0.29.1.dev408__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.
Files changed (57) hide show
  1. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/PKG-INFO +22 -1
  2. autoverse_cli-0.29.1.dev408/README.md +64 -0
  3. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/pyproject.toml +1 -1
  4. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/PKG-INFO +22 -1
  5. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/app_version.py +1 -1
  6. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/race_cloud.py +86 -16
  7. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/race_cloud_cfg_util.py +4 -30
  8. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/race_cloud_util.py +50 -37
  9. autoverse_cli-0.28.3/README.md +0 -43
  10. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/LICENSE +0 -0
  11. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/setup.cfg +0 -0
  12. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/SOURCES.txt +0 -0
  13. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/dependency_links.txt +0 -0
  14. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/entry_points.txt +0 -0
  15. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/requires.txt +0 -0
  16. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/autoverse_cli.egg-info/top_level.txt +0 -0
  17. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/__init__.py +0 -0
  18. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/argparse_help.py +0 -0
  19. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/avrs.py +0 -0
  20. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/can_tool.py +0 -0
  21. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/can_tool_util.py +0 -0
  22. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/cfg.py +0 -0
  23. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/launcher.py +0 -0
  24. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/launcher_util.py +0 -0
  25. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/race_cloud_bridge_can.py +0 -0
  26. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/race_cloud_fwd_api.py +0 -0
  27. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/change_camera.py +0 -0
  28. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/code_booz.py +0 -0
  29. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/demo.py +0 -0
  30. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/dump_sim_config.py +0 -0
  31. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/environment.py +0 -0
  32. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/fault_injection.py +0 -0
  33. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/get_object_config.py +0 -0
  34. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/get_web_viz_meta.py +0 -0
  35. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/leaderboard.py +0 -0
  36. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/list_sim_objects.py +0 -0
  37. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/log_path.py +0 -0
  38. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/misc.py +0 -0
  39. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/move_to_landmark.py +0 -0
  40. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/npc.py +0 -0
  41. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/race_control.py +0 -0
  42. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/request.py +0 -0
  43. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/reset_to_track.py +0 -0
  44. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/rest_request.py +0 -0
  45. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/restart.py +0 -0
  46. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/scenario_control.py +0 -0
  47. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/spawn_object.py +0 -0
  48. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/teleport.py +0 -0
  49. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/toggle_hud.py +0 -0
  50. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/vd.py +0 -0
  51. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/vehicle_input.py +0 -0
  52. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/requests/vehicle_replay.py +0 -0
  53. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/shell_completion.py +0 -0
  54. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/simconfig.py +0 -0
  55. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/simconfig_util.py +0 -0
  56. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/tests.py +0 -0
  57. {autoverse_cli-0.28.3 → autoverse_cli-0.29.1.dev408}/src/avrs/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autoverse-cli
3
- Version: 0.28.3
3
+ Version: 0.29.1.dev408
4
4
  Summary: The Autoverse CLI
5
5
  Author-email: Dan Kamrath <dan.kamrath@autonomalabs.com>
6
6
  License: # End-User License Agreement (EULA) of the Autonoma AutoVerse CLI
@@ -52,10 +52,31 @@ The new implementation of the Autoverse CLI
52
52
 
53
53
  ## Installation
54
54
 
55
+ ### Stable Release (Recommended)
55
56
  ```bash
56
57
  pip install autoverse-cli
57
58
  ```
58
59
 
60
+ ### Development Versions
61
+
62
+ Development versions are published from feature branches and follow the format `X.Y.Z.devN`.
63
+
64
+ ```bash
65
+ # Install the latest development version
66
+ pip install autoverse-cli --pre
67
+
68
+ # Install a specific development version
69
+ pip install autoverse-cli==0.29.1.dev123
70
+
71
+ # Check available versions (including dev)
72
+ pip index versions autoverse-cli
73
+
74
+ # Upgrade to latest dev version
75
+ pip install --upgrade --pre autoverse-cli
76
+ ```
77
+
78
+ > **Note:** `pip install autoverse-cli` (without `--pre`) always installs the latest stable release from `main`. Development versions require the `--pre` flag explicitly.
79
+
59
80
  ## Shell Completion
60
81
 
61
82
  To enable tab completion for the `avrs` command, run:
@@ -0,0 +1,64 @@
1
+ # Autoverse CLI
2
+
3
+ The new implementation of the Autoverse CLI
4
+
5
+ ## Installation
6
+
7
+ ### Stable Release (Recommended)
8
+ ```bash
9
+ pip install autoverse-cli
10
+ ```
11
+
12
+ ### Development Versions
13
+
14
+ Development versions are published from feature branches and follow the format `X.Y.Z.devN`.
15
+
16
+ ```bash
17
+ # Install the latest development version
18
+ pip install autoverse-cli --pre
19
+
20
+ # Install a specific development version
21
+ pip install autoverse-cli==0.29.1.dev123
22
+
23
+ # Check available versions (including dev)
24
+ pip index versions autoverse-cli
25
+
26
+ # Upgrade to latest dev version
27
+ pip install --upgrade --pre autoverse-cli
28
+ ```
29
+
30
+ > **Note:** `pip install autoverse-cli` (without `--pre`) always installs the latest stable release from `main`. Development versions require the `--pre` flag explicitly.
31
+
32
+ ## Shell Completion
33
+
34
+ To enable tab completion for the `avrs` command, run:
35
+
36
+ ```bash
37
+ avrs --install-completion
38
+ ```
39
+
40
+ Then reload your shell:
41
+
42
+ ```bash
43
+ source ~/.bashrc # or ~/.zshrc, ~/.config/fish/config.fish, etc.
44
+ ```
45
+
46
+ For full details, see [SHELL_COMPLETION.md](SHELL_COMPLETION.md).
47
+
48
+ ### Supported Shells
49
+
50
+ - Bash
51
+ - Zsh
52
+ - Fish
53
+ - Tcsh
54
+
55
+ ### Quick Usage Examples
56
+
57
+ ```bash
58
+ # List all available commands
59
+ avrs <TAB>
60
+
61
+ # Complete subcommand arguments
62
+ avrs launcher <TAB>
63
+ avrs restart <TAB>
64
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "autoverse-cli"
3
- version = "0.28.3"
3
+ version = "0.29.1.dev408"
4
4
  dependencies = [
5
5
  "boto3",
6
6
  "cantools",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autoverse-cli
3
- Version: 0.28.3
3
+ Version: 0.29.1.dev408
4
4
  Summary: The Autoverse CLI
5
5
  Author-email: Dan Kamrath <dan.kamrath@autonomalabs.com>
6
6
  License: # End-User License Agreement (EULA) of the Autonoma AutoVerse CLI
@@ -52,10 +52,31 @@ The new implementation of the Autoverse CLI
52
52
 
53
53
  ## Installation
54
54
 
55
+ ### Stable Release (Recommended)
55
56
  ```bash
56
57
  pip install autoverse-cli
57
58
  ```
58
59
 
60
+ ### Development Versions
61
+
62
+ Development versions are published from feature branches and follow the format `X.Y.Z.devN`.
63
+
64
+ ```bash
65
+ # Install the latest development version
66
+ pip install autoverse-cli --pre
67
+
68
+ # Install a specific development version
69
+ pip install autoverse-cli==0.29.1.dev123
70
+
71
+ # Check available versions (including dev)
72
+ pip index versions autoverse-cli
73
+
74
+ # Upgrade to latest dev version
75
+ pip install --upgrade --pre autoverse-cli
76
+ ```
77
+
78
+ > **Note:** `pip install autoverse-cli` (without `--pre`) always installs the latest stable release from `main`. Development versions require the `--pre` flag explicitly.
79
+
59
80
  ## Shell Completion
60
81
 
61
82
  To enable tab completion for the `avrs` command, run:
@@ -2,7 +2,7 @@ import http.client
2
2
  import json
3
3
 
4
4
  def get_app_version():
5
- return '0.28.2'
5
+ return '0.29.1.dev408'
6
6
 
7
7
  def check_app_is_latest():
8
8
  pass
@@ -2,6 +2,7 @@ import subprocess
2
2
  import base64
3
3
  import logging
4
4
  import time
5
+ import ipaddress
5
6
  from avrs.cfg import *
6
7
  from avrs.race_cloud_util import *
7
8
  from avrs.race_cloud_cfg_util import *
@@ -11,6 +12,47 @@ from avrs.util import *
11
12
  from avrs.requests.request import AvrsApiRequest
12
13
  from argparse import RawTextHelpFormatter
13
14
 
15
+
16
+ def is_valid_public_ip(value):
17
+ """Check if a string is a valid public IP address (not private, not loopback, not reserved)."""
18
+ try:
19
+ ip = ipaddress.ip_address(value)
20
+ # Reject private, loopback, reserved, multicast, and link-local addresses
21
+ return not (ip.is_private or ip.is_loopback or ip.is_reserved or
22
+ ip.is_multicast or ip.is_link_local)
23
+ except ValueError:
24
+ return False
25
+
26
+
27
+ def parse_sim_target(value):
28
+ """
29
+ Parse sim_target argument: can be a legacy index (0-5) or a public IP address.
30
+ Returns (is_valid, parsed_value, is_ip).
31
+ """
32
+ # First, check if it's a legacy integer index (0-5)
33
+ try:
34
+ index = int(value)
35
+ if 0 <= index <= 5:
36
+ return (True, index, False)
37
+ else:
38
+ return (False, "Legacy index must be between 0 and 5", False)
39
+ except ValueError:
40
+ pass
41
+
42
+ # Check if it's a valid public IP address
43
+ try:
44
+ ip = ipaddress.ip_address(value)
45
+ if is_valid_public_ip(value):
46
+ # Valid public IP address
47
+ return (True, value, True)
48
+ else:
49
+ # IP is private, loopback, or otherwise not public
50
+ return (False, "IP address must be public (not private, loopback, or reserved)", False)
51
+ except ValueError:
52
+ pass
53
+
54
+ return (False, "Must be a legacy index (0-5) or a valid public IP address", False)
55
+
14
56
  class AvrsRaceCloud(AvrsApiRequest):
15
57
  def __init__(self, parser, cfg):
16
58
  self.cfg = cfg
@@ -24,10 +66,9 @@ class AvrsRaceCloud(AvrsApiRequest):
24
66
  'connect',
25
67
  help='connect to an instance for cloud racing')
26
68
  connect_parser.add_argument(
27
- 'sim_index',
28
- type = int,
29
- choices = [0, 1, 2, 3, 4, 5],
30
- help='the index of the simulator instance to connect to')
69
+ 'sim_target',
70
+ type=str,
71
+ help='simulator target: legacy index (0-5) or PUBLIC IP address of the server instance (private IPs not allowed)')
31
72
  connect_parser.add_argument(
32
73
  'team_name',
33
74
  help='the name of the team to race under')
@@ -74,10 +115,9 @@ class AvrsRaceCloud(AvrsApiRequest):
74
115
  'sim-ctrl',
75
116
  help='control the sim program (start, stop, restart, reset)')
76
117
  sim_ctrl_parser.add_argument(
77
- 'sim_index',
78
- type=int,
79
- choices=[0, 1, 2, 3, 4, 5],
80
- help='the index of the simulator instance to apply the action')
118
+ 'sim_target',
119
+ type=str,
120
+ help='simulator target: legacy index (0-5) or PUBLIC IP address of the server instance (private IPs not allowed)')
81
121
  sim_ctrl_parser.add_argument(
82
122
  'action',
83
123
  choices=['start', 'stop', 'restart', 'reset-connection', 'get-log'],
@@ -169,6 +209,12 @@ class AvrsRaceCloud(AvrsApiRequest):
169
209
  def race_connect(self, args):
170
210
  logger = logging.getLogger('avrs')
171
211
 
212
+ # Validate sim_target (can be legacy index 0-5 or public IP only)
213
+ is_valid, parsed_value, is_ip = parse_sim_target(args.sim_target)
214
+ if not is_valid:
215
+ print('invalid sim_target: {}'.format(parsed_value))
216
+ return
217
+
172
218
  # make api call to begin connection
173
219
  our_ip = get_local_instance_ip()
174
220
 
@@ -176,8 +222,9 @@ class AvrsRaceCloud(AvrsApiRequest):
176
222
  print('this machines IP was returned as localhost. was this run on the cloud instance?')
177
223
  return
178
224
 
179
- logger.info('starting race-cloud connect for team {} to instance {}'.format(
180
- args.team_name, args.sim_index))
225
+ target_display = args.sim_target if is_ip else 'index {}'.format(parsed_value)
226
+ logger.info('starting race-cloud connect for team {} to {}'.format(
227
+ args.team_name, target_display))
181
228
  print('connecting to race with team name: {}'.format(args.team_name))
182
229
 
183
230
  if args.no_restart_sim:
@@ -217,7 +264,7 @@ class AvrsRaceCloud(AvrsApiRequest):
217
264
 
218
265
  connection_request = {
219
266
  'action': 'connect',
220
- 'sim_index': args.sim_index,
267
+ 'sim_id': str(parsed_value), # Can be index (0-5) or public IP address only
221
268
  'ip_to_reserve': our_ip,
222
269
  'team_name': args.team_name,
223
270
  'sim_id_override': args.instance_id,
@@ -229,7 +276,6 @@ class AvrsRaceCloud(AvrsApiRequest):
229
276
  ok, response = call_race_cloud_api(connection_request)
230
277
  if not ok:
231
278
  print('connect api error: {}'.format(response))
232
- return
233
279
 
234
280
  ok, rbody, sim_ip = get_api_script_response(response)
235
281
  if not ok:
@@ -242,9 +288,27 @@ class AvrsRaceCloud(AvrsApiRequest):
242
288
 
243
289
  slot_info = {}
244
290
  for k, v in rbody.items():
245
- #print('out: {}'.format(v['stdout']))
246
- #print('err: {}'.format(v['stderr']))
247
- slot_info = json.loads(v['stdout'])
291
+ logger.info('Processing response for key: {}'.format(k))
292
+ logger.info('stdout: {}'.format(v.get('stdout', '')))
293
+ logger.info('stderr: {}'.format(v.get('stderr', '')))
294
+
295
+ stdout = v.get('stdout', '').strip()
296
+ stderr = v.get('stderr', '').strip()
297
+
298
+ if not stdout:
299
+ print('Error: No stdout from remote command')
300
+ if stderr:
301
+ print('stderr: {}'.format(stderr))
302
+ return
303
+
304
+ try:
305
+ slot_info = json.loads(stdout)
306
+ except json.JSONDecodeError as e:
307
+ print('Error parsing JSON from stdout: {}'.format(e))
308
+ print('stdout content: {}'.format(stdout[:500])) # Print first 500 chars
309
+ if stderr:
310
+ print('stderr: {}'.format(stderr))
311
+ return
248
312
 
249
313
  if not slot_info['ok']:
250
314
  print('issue reserving slot: {}'.format(slot_info['msg']))
@@ -406,6 +470,12 @@ class AvrsRaceCloud(AvrsApiRequest):
406
470
  def remote_sim_ctrl(self, args):
407
471
  logger = logging.getLogger('avrs')
408
472
 
473
+ # Validate sim_target (can be legacy index 0-5 or public IP only)
474
+ is_valid, parsed_value, is_ip = parse_sim_target(args.sim_target)
475
+ if not is_valid:
476
+ print('invalid sim_target: {}'.format(parsed_value))
477
+ return
478
+
409
479
  # go ahead and reset local connection as well
410
480
  if args.action == 'reset-connection':
411
481
  reset_race_cloud_connection()
@@ -414,7 +484,7 @@ class AvrsRaceCloud(AvrsApiRequest):
414
484
 
415
485
  reset_request = {
416
486
  'action': args.action,
417
- 'sim_index': args.sim_index,
487
+ 'sim_id': str(parsed_value), # Can be index (0-5) or public IP address only
418
488
  'ip_to_reserve': our_ip,
419
489
  'sim_id_override': args.instance_id,
420
490
  'ensure_instance_is_running': False
@@ -78,13 +78,13 @@ def register_received_vehicle(team_name, slot, cfg_data, bsu_vcan, kistler_vcan,
78
78
  if eav24 is None:
79
79
  return (False, 'no eav24 payload found')
80
80
 
81
- #logger.info('disabling perception for received vehicle config')
82
- # eav24['body']['bLidarEnabled'] = False
81
+ logger.info('disabling perception for received vehicle config')
82
+ eav24['body']['bLidarEnabled'] = False
83
83
  eav24['body']['bCameraEnabled'] = False
84
84
  eav24['body']['bRadarEnabled'] = False
85
- # eav24['body']['bPublishGroundTruth'] = False
85
+ eav24['body']['bPublishGroundTruth'] = False
86
86
  eav24['body']['bPublishInputs'] = False
87
- eav24['body']['bRenderHudInWorld'] = False
87
+ eav24['body']['bRenderHudInWorld'] = True
88
88
 
89
89
  # do not disable HUD
90
90
  #logger.info('disabling hud for received vehicle config')
@@ -208,32 +208,6 @@ def register_received_vehicle(team_name, slot, cfg_data, bsu_vcan, kistler_vcan,
208
208
  logger.info("opponentGroundTruthDsd rate was > 100. clamping")
209
209
  gtc["body"]["opponentGroundTruthDsd"]["rateHz"] = 100
210
210
 
211
- # clamp lidar rates
212
- for payload in cfg_object['payloads']:
213
- if payload['typeName'].lower() == 'genericlidaripd':
214
- lidar_rate = payload.get("body", {}).get("sensorDesc", {}).get("dataStream", {}).get("rateHz", 0)
215
- if lidar_rate > 20:
216
- instance_name = payload.get("body", {}).get("componentConfig", {}).get("instanceName", "unknown")
217
- logger.info("lidar {} rate was > 20. clamping".format(instance_name))
218
- payload["body"]["sensorDesc"]["dataStream"]["rateHz"] = 20
219
-
220
- # clamp camera rates
221
- for payload in cfg_object['payloads']:
222
- if payload['typeName'].lower() == 'camerasensor':
223
- camera_rate = payload.get("body", {}).get("sensorDesc", {}).get("dataStream", {}).get("rateHz", 0)
224
- if camera_rate > 20:
225
- instance_name = payload.get("body", {}).get("componentConfig", {}).get("instanceName", "unknown")
226
- logger.info("camera {} rate was > 20. clamping".format(instance_name))
227
- payload["body"]["sensorDesc"]["dataStream"]["rateHz"] = 20
228
-
229
- # clamp radar rates
230
- for payload in cfg_object['payloads']:
231
- if payload['typeName'].lower() == 'radarsensor':
232
- radar_rate = payload.get("body", {}).get("sensorDesc", {}).get("dataStream", {}).get("rateHz", 0)
233
- if radar_rate > 20:
234
- instance_name = payload.get("body", {}).get("componentConfig", {}).get("instanceName", "unknown")
235
- logger.info("radar {} rate was > 20. clamping".format(instance_name))
236
- payload["body"]["sensorDesc"]["dataStream"]["rateHz"] = 20
237
211
 
238
212
  # do not allow default object name (collision)
239
213
  if cfg_object['name'] == 'eav24':
@@ -1,7 +1,10 @@
1
1
  import os
2
2
  import json
3
- import http.client
4
3
  import logging
4
+ import boto3
5
+ from botocore.auth import SigV4Auth
6
+ from botocore.awsrequest import AWSRequest
7
+ import urllib.request
5
8
  from avrs.util import *
6
9
 
7
10
  BASH_KILL_PROCESS_SCRIPT = '''
@@ -360,45 +363,55 @@ def call_race_cloud_api(body):
360
363
  logger = logging.getLogger('avrs')
361
364
  logger.info('calling race-cloud api with body: {}'.format(body))
362
365
 
363
- api_url = 'gitzels0l7.execute-api.us-east-1.amazonaws.com'
366
+ url = 'https://9gca6018p0.execute-api.us-east-1.amazonaws.com/backend/race-connect'
367
+ region = 'us-east-1'
364
368
 
365
- connection = http.client.HTTPSConnection(api_url)
366
- headers = {
367
- 'Content-type': 'application/json',
368
- 'x-api-key': '7aQ83sJ89Q2DZ8NdIi9aUTBuUS2uyix5QoDwrl1j'
369
- }
370
- body = json.dumps(body).encode('utf-8')
371
- connection.request('POST', '/beta/connect', body, headers)
372
- response = connection.getresponse()
373
- if response.status != 200:
374
- return (False, 'response had status code {}'.format(response))
375
- return (True, response.read().decode('utf-8'))
376
-
377
- def get_api_script_response(raw):
378
- logger = logging.getLogger('avrs')
379
- try:
380
- parsed = json.loads(raw)
381
- decoded = parsed['body']
369
+ # Get credentials from boto3 session (uses IAM role on EC2)
370
+ session = boto3.Session()
371
+ credentials = session.get_credentials()
382
372
 
383
- # Handle double-encoded JSON (body is a string instead of dict)
384
- if isinstance(decoded, str):
385
- decoded = json.loads(decoded)
373
+ # Prepare the request body
374
+ body_json = json.dumps(body)
386
375
 
387
- logger.info('race cloud api response: {}'.format(decoded))
376
+ # Create AWS request for signing
377
+ request = AWSRequest(
378
+ method='POST',
379
+ url=url,
380
+ data=body_json,
381
+ headers={'Content-Type': 'application/json'}
382
+ )
388
383
 
389
- if 'script_response' not in decoded:
390
- return (False, 'missing script_response in response: {}'.format(decoded), None)
384
+ # Sign the request with SigV4
385
+ SigV4Auth(credentials, 'execute-api', region).add_auth(request)
391
386
 
392
- if decoded['script_response']['statusCode'] != 200:
393
- return (False, 'inner response had bad status code {}'.format(decoded), None)
394
-
395
- return (True, json.loads(decoded['script_response']['body']), decoded['sim_private_ip'])
396
- except json.JSONDecodeError as e:
397
- logger.error('failed to parse API response as JSON: {}'.format(e))
398
- return (False, 'invalid JSON response: {}'.format(raw[:500]), None)
399
- except KeyError as e:
400
- logger.error('missing expected key in API response: {}'.format(e))
401
- return (False, 'missing key {} in response: {}'.format(e, raw[:500]), None)
387
+ # Make the request using urllib
388
+ try:
389
+ req = urllib.request.Request(
390
+ url,
391
+ data=body_json.encode('utf-8'),
392
+ headers=dict(request.headers),
393
+ method='POST'
394
+ )
395
+ with urllib.request.urlopen(req) as response:
396
+ response_body = response.read().decode('utf-8')
397
+ return (True, response_body)
398
+ except urllib.error.HTTPError as e:
399
+ error_body = e.read().decode('utf-8')
400
+ logger.error('API error - status: {}, body: {}'.format(e.code, error_body))
401
+ return (False, 'response had status code {} - {}'.format(e.code, error_body))
402
402
  except Exception as e:
403
- logger.error('unexpected error parsing API response: {}'.format(e))
404
- return (False, 'error parsing response: {}'.format(e), None)
403
+ logger.error('API request failed: {}'.format(str(e)))
404
+ return (False, 'request failed: {}'.format(str(e)))
405
+
406
+ def get_api_script_response(raw):
407
+ logger = logging.getLogger('avrs')
408
+ # Parse API Gateway response, then parse the body which is also JSON string
409
+ api_response = json.loads(raw)
410
+ body_str = api_response['body']
411
+ # Body is a JSON string from Lambda Proxy integration
412
+ decoded = json.loads(body_str) if isinstance(body_str, str) else body_str
413
+ logger.info('race cloud api response: {}'.format(decoded))
414
+ if decoded['script_response']['statusCode'] != 200:
415
+ return (False, 'inner response had bad status code {}'.format(decoded))
416
+ #print(decoded)
417
+ return (True, json.loads(decoded['script_response']['body']), decoded['sim_private_ip'])
@@ -1,43 +0,0 @@
1
- # Autoverse CLI
2
-
3
- The new implementation of the Autoverse CLI
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pip install autoverse-cli
9
- ```
10
-
11
- ## Shell Completion
12
-
13
- To enable tab completion for the `avrs` command, run:
14
-
15
- ```bash
16
- avrs --install-completion
17
- ```
18
-
19
- Then reload your shell:
20
-
21
- ```bash
22
- source ~/.bashrc # or ~/.zshrc, ~/.config/fish/config.fish, etc.
23
- ```
24
-
25
- For full details, see [SHELL_COMPLETION.md](SHELL_COMPLETION.md).
26
-
27
- ### Supported Shells
28
-
29
- - Bash
30
- - Zsh
31
- - Fish
32
- - Tcsh
33
-
34
- ### Quick Usage Examples
35
-
36
- ```bash
37
- # List all available commands
38
- avrs <TAB>
39
-
40
- # Complete subcommand arguments
41
- avrs launcher <TAB>
42
- avrs restart <TAB>
43
- ```