rosotacom-dev 2.5.dev8__tar.gz → 2.5.dev10__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.
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/PKG-INFO +29 -1
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/README.md +28 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/cli.py +210 -28
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/PKG-INFO +29 -1
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/scm_version.json +2 -2
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_cli.py +227 -2
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/install.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/justfile +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/run_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/session-configuration.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/SOURCES.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/scm_file_list.json +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/stop_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_security_maintenance_config.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/conftest.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev8 → rosotacom_dev-2.5.dev10}/tests/unit/test_video_quality.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev10
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -494,6 +494,34 @@ in this mode — there is no staging to undo, and the workdir is your repository
|
|
|
494
494
|
The run manifest records which mode and which version the peers ran, so a result
|
|
495
495
|
can be attributed to an artefact rather than to a working copy.
|
|
496
496
|
|
|
497
|
+
#### How the peers are reached: `--peer-exec`
|
|
498
|
+
|
|
499
|
+
`--peer-ssh` gives the orchestrator a shell on the peer, which is more than a
|
|
500
|
+
run needs and more than some machines should hand out. `--peer-exec` names the
|
|
501
|
+
transport instead:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
505
|
+
--install-mode checkout \
|
|
506
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt \
|
|
507
|
+
--peer-exec b='remote-rosotacom robot'
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The command is run with the script as its final argument — the contract
|
|
511
|
+
`ssh host <script>` already has — so anything of that shape can carry a peer: a
|
|
512
|
+
wrapper that logs what a run asks for, a container exec, or a forced command
|
|
513
|
+
that accepts some scripts and refuses the rest. rosotacom does not know or care
|
|
514
|
+
which; it only stops assuming that reaching a peer means having a shell on it.
|
|
515
|
+
|
|
516
|
+
Two restrictions, both load-bearing. It applies to `--install-mode checkout`
|
|
517
|
+
only, because the staging modes push a tar stream and a file write by taking
|
|
518
|
+
the ssh client's own argv apart, and a transport that promises no more than
|
|
519
|
+
"run this script" cannot carry them. And a peer takes either `--peer-ssh` or
|
|
520
|
+
`--peer-exec`, never both: leaving it ambiguous hides which one carried the run.
|
|
521
|
+
|
|
522
|
+
`-t` and `-o BatchMode=yes` are dropped rather than forwarded. They are options
|
|
523
|
+
of one client, and a transport that is not ssh never agreed to understand them.
|
|
524
|
+
|
|
497
525
|
### Live status / debugging overview
|
|
498
526
|
|
|
499
527
|
Enable a continuously-updated, per-topic pipeline overview by setting
|
|
@@ -449,6 +449,34 @@ in this mode — there is no staging to undo, and the workdir is your repository
|
|
|
449
449
|
The run manifest records which mode and which version the peers ran, so a result
|
|
450
450
|
can be attributed to an artefact rather than to a working copy.
|
|
451
451
|
|
|
452
|
+
#### How the peers are reached: `--peer-exec`
|
|
453
|
+
|
|
454
|
+
`--peer-ssh` gives the orchestrator a shell on the peer, which is more than a
|
|
455
|
+
run needs and more than some machines should hand out. `--peer-exec` names the
|
|
456
|
+
transport instead:
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
460
|
+
--install-mode checkout \
|
|
461
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt \
|
|
462
|
+
--peer-exec b='remote-rosotacom robot'
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
The command is run with the script as its final argument — the contract
|
|
466
|
+
`ssh host <script>` already has — so anything of that shape can carry a peer: a
|
|
467
|
+
wrapper that logs what a run asks for, a container exec, or a forced command
|
|
468
|
+
that accepts some scripts and refuses the rest. rosotacom does not know or care
|
|
469
|
+
which; it only stops assuming that reaching a peer means having a shell on it.
|
|
470
|
+
|
|
471
|
+
Two restrictions, both load-bearing. It applies to `--install-mode checkout`
|
|
472
|
+
only, because the staging modes push a tar stream and a file write by taking
|
|
473
|
+
the ssh client's own argv apart, and a transport that promises no more than
|
|
474
|
+
"run this script" cannot carry them. And a peer takes either `--peer-ssh` or
|
|
475
|
+
`--peer-exec`, never both: leaving it ambiguous hides which one carried the run.
|
|
476
|
+
|
|
477
|
+
`-t` and `-o BatchMode=yes` are dropped rather than forwarded. They are options
|
|
478
|
+
of one client, and a transport that is not ssh never agreed to understand them.
|
|
479
|
+
|
|
452
480
|
### Live status / debugging overview
|
|
453
481
|
|
|
454
482
|
Enable a continuously-updated, per-topic pipeline overview by setting
|
|
@@ -234,6 +234,19 @@ class OtaSmokePeer:
|
|
|
234
234
|
#: control centre runs it under a different account than a laptop does — and
|
|
235
235
|
#: a single workdir would silently be wrong on all but one of them.
|
|
236
236
|
checkout: str | None = None
|
|
237
|
+
#: How to reach this peer, when `ssh <alias> <script>` is not allowed to be
|
|
238
|
+
#: the answer. The command is given the script as its final argument, the
|
|
239
|
+
#: same contract ssh has, so anything with that shape can carry a peer:
|
|
240
|
+
#: a wrapper that logs, a container exec, or a capability that accepts only
|
|
241
|
+
#: some scripts and refuses the rest.
|
|
242
|
+
#:
|
|
243
|
+
#: This exists because "give the orchestrator a shell on the peer" is a poor
|
|
244
|
+
#: trade for a machine that is only meant to run one repository's test. An
|
|
245
|
+
#: SSH alias grants everything that account can do, forever, to whoever
|
|
246
|
+
#: holds the key; the operations a run actually needs are a short, fixed
|
|
247
|
+
#: list. Naming the transport lets the narrow thing be substituted without
|
|
248
|
+
#: this file having to know what narrow means.
|
|
249
|
+
exec_command: str | None = None
|
|
237
250
|
|
|
238
251
|
|
|
239
252
|
@dataclass(frozen=True)
|
|
@@ -1027,6 +1040,10 @@ def _parse_peer_checkout_overrides(overrides: list[str] | None) -> dict[str, str
|
|
|
1027
1040
|
return parse_assignments(overrides, option="--peer-checkout")
|
|
1028
1041
|
|
|
1029
1042
|
|
|
1043
|
+
def _parse_peer_exec_overrides(overrides: list[str] | None) -> dict[str, str]:
|
|
1044
|
+
return parse_assignments(overrides, option="--peer-exec")
|
|
1045
|
+
|
|
1046
|
+
|
|
1030
1047
|
def _deployment_config(runtime: RuntimeConfig) -> DeploymentConfig | None:
|
|
1031
1048
|
return load_deployment(runtime.deployment)
|
|
1032
1049
|
|
|
@@ -1563,8 +1580,31 @@ def _ota_plan_from_bindings(
|
|
|
1563
1580
|
install_pin: str | None = None,
|
|
1564
1581
|
checkouts: Mapping[str, str] | None = None,
|
|
1565
1582
|
project: str | None = None,
|
|
1583
|
+
exec_commands: Mapping[str, str] | None = None,
|
|
1566
1584
|
) -> OtaSmokePlan:
|
|
1567
1585
|
_ota_validate_install_mode(install_mode)
|
|
1586
|
+
if exec_commands:
|
|
1587
|
+
unknown = sorted(set(exec_commands) - set(bindings))
|
|
1588
|
+
if unknown:
|
|
1589
|
+
raise RuntimeError(f"--peer-exec names a peer the session does not have: {', '.join(unknown)}")
|
|
1590
|
+
# Staging modes send a tar stream and a file write, not a command, and
|
|
1591
|
+
# both take the ssh client's own argv apart to do it. A transport that
|
|
1592
|
+
# only promises "run this script" cannot carry them, and quietly
|
|
1593
|
+
# writing the peer's files onto the orchestrator instead — which is
|
|
1594
|
+
# what the local branch of the staging helpers would do — is the worst
|
|
1595
|
+
# of the available outcomes.
|
|
1596
|
+
if install_mode != "checkout":
|
|
1597
|
+
raise RuntimeError(
|
|
1598
|
+
f"--peer-exec requires --install-mode checkout (got {install_mode!r}): the other modes copy a "
|
|
1599
|
+
"tree to the peer, which a command transport cannot carry."
|
|
1600
|
+
)
|
|
1601
|
+
both = sorted(name for name in exec_commands if bindings[name].ssh)
|
|
1602
|
+
if both:
|
|
1603
|
+
raise RuntimeError(
|
|
1604
|
+
"--peer-exec and --peer-ssh both name "
|
|
1605
|
+
+ ", ".join(both)
|
|
1606
|
+
+ "; a peer is reached one way, and leaving it ambiguous hides which one carried the run."
|
|
1607
|
+
)
|
|
1568
1608
|
if install_mode == "checkout":
|
|
1569
1609
|
if not checkouts or not project:
|
|
1570
1610
|
raise RuntimeError("--install-mode checkout requires --peer-checkout for every peer.")
|
|
@@ -1602,6 +1642,7 @@ def _ota_plan_from_bindings(
|
|
|
1602
1642
|
ssh=binding.ssh,
|
|
1603
1643
|
address=binding.address,
|
|
1604
1644
|
checkout=(checkouts or {}).get(name) if install_mode == "checkout" else None,
|
|
1645
|
+
exec_command=(exec_commands or {}).get(name),
|
|
1605
1646
|
)
|
|
1606
1647
|
for name, binding in bindings.items()
|
|
1607
1648
|
}
|
|
@@ -1619,14 +1660,19 @@ def _ota_plan_from_bindings(
|
|
|
1619
1660
|
def _ota_write_state(instance: SessionInstance, plan: OtaSmokePlan) -> OtaSmokePlan:
|
|
1620
1661
|
path = instance.host_dir / "ota-deployment.yaml"
|
|
1621
1662
|
payload = {
|
|
1622
|
-
"schema_version":
|
|
1663
|
+
"schema_version": 4,
|
|
1623
1664
|
"workdir": plan.workdir,
|
|
1624
1665
|
"rosotacom": plan.rosotacom,
|
|
1625
1666
|
"project": plan.project,
|
|
1626
1667
|
"install_mode": plan.install_mode,
|
|
1627
1668
|
"install_pin": plan.install_pin,
|
|
1628
1669
|
"peers": {
|
|
1629
|
-
name: {
|
|
1670
|
+
name: {
|
|
1671
|
+
"address": peer.address,
|
|
1672
|
+
"ssh": peer.ssh,
|
|
1673
|
+
"checkout": peer.checkout,
|
|
1674
|
+
"exec": peer.exec_command,
|
|
1675
|
+
}
|
|
1630
1676
|
for name, peer in sorted(plan.peers.items())
|
|
1631
1677
|
},
|
|
1632
1678
|
}
|
|
@@ -1637,7 +1683,7 @@ def _ota_write_state(instance: SessionInstance, plan: OtaSmokePlan) -> OtaSmokeP
|
|
|
1637
1683
|
def _ota_load_state(path_arg: str) -> OtaSmokePlan:
|
|
1638
1684
|
path = Path(path_arg).expanduser().resolve()
|
|
1639
1685
|
raw = _load_yaml_file(path)
|
|
1640
|
-
if raw.get("schema_version") !=
|
|
1686
|
+
if raw.get("schema_version") != 4:
|
|
1641
1687
|
raise RuntimeError(f"Unsupported OTA deployment state: {path}")
|
|
1642
1688
|
peers_raw = raw.get("peers")
|
|
1643
1689
|
if not isinstance(peers_raw, dict) or len(peers_raw) != 2:
|
|
@@ -1651,6 +1697,7 @@ def _ota_load_state(path_arg: str) -> OtaSmokePlan:
|
|
|
1651
1697
|
address=str(peer_raw["address"]),
|
|
1652
1698
|
ssh=str(peer_raw["ssh"]) if peer_raw.get("ssh") else None,
|
|
1653
1699
|
checkout=str(peer_raw["checkout"]) if peer_raw.get("checkout") else None,
|
|
1700
|
+
exec_command=str(peer_raw["exec"]) if peer_raw.get("exec") else None,
|
|
1654
1701
|
)
|
|
1655
1702
|
install_pin = raw.get("install_pin")
|
|
1656
1703
|
return OtaSmokePlan(
|
|
@@ -1682,7 +1729,32 @@ def _ota_quote_cmd(parts: list[str]) -> str:
|
|
|
1682
1729
|
return shlex.join(parts)
|
|
1683
1730
|
|
|
1684
1731
|
|
|
1732
|
+
def _ota_peer_is_remote(peer: OtaSmokePeer) -> bool:
|
|
1733
|
+
"""Does this peer run somewhere other than the orchestrator?
|
|
1734
|
+
|
|
1735
|
+
Asked as a question about the peer rather than about SSH. Every caller that
|
|
1736
|
+
used to read ``peer.ssh`` for this meant "is it over there", and each one
|
|
1737
|
+
that kept reading it after a second transport existed would have taken the
|
|
1738
|
+
local branch for a machine on the other side of the room.
|
|
1739
|
+
"""
|
|
1740
|
+
return bool(peer.ssh or peer.exec_command)
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
def _ota_peer_target(peer: OtaSmokePeer) -> str:
|
|
1744
|
+
"""How to name this peer's location in output meant for a human."""
|
|
1745
|
+
if peer.exec_command:
|
|
1746
|
+
return peer.exec_command
|
|
1747
|
+
return peer.ssh or "local shell"
|
|
1748
|
+
|
|
1749
|
+
|
|
1685
1750
|
def _ota_remote_argv(peer: OtaSmokePeer, script: str, *, tty: bool = False, batch: bool = False) -> list[str]:
|
|
1751
|
+
# A named transport wins over the SSH alias, and it takes the script as its
|
|
1752
|
+
# last argument because that is the contract `ssh host <script>` already
|
|
1753
|
+
# has. `tty` and `batch` are dropped on purpose rather than guessed at:
|
|
1754
|
+
# they are options of one particular client, and a transport that is not
|
|
1755
|
+
# ssh has no obligation to understand them.
|
|
1756
|
+
if peer.exec_command:
|
|
1757
|
+
return [*shlex.split(peer.exec_command), script]
|
|
1686
1758
|
if peer.ssh:
|
|
1687
1759
|
argv = ["ssh"]
|
|
1688
1760
|
if batch:
|
|
@@ -2194,7 +2266,12 @@ def _ota_write_manifest(
|
|
|
2194
2266
|
"install_mode": plan.install_mode,
|
|
2195
2267
|
"install_pin": plan.install_pin,
|
|
2196
2268
|
"peers": {
|
|
2197
|
-
name: {
|
|
2269
|
+
name: {
|
|
2270
|
+
"ssh_configured": bool(peer.ssh),
|
|
2271
|
+
"exec_configured": bool(peer.exec_command),
|
|
2272
|
+
"address": peer.address,
|
|
2273
|
+
}
|
|
2274
|
+
for name, peer in plan.peers.items()
|
|
2198
2275
|
},
|
|
2199
2276
|
},
|
|
2200
2277
|
)
|
|
@@ -2378,6 +2455,7 @@ def _resolve_ota_smoke_context(
|
|
|
2378
2455
|
)
|
|
2379
2456
|
install_mode = str(getattr(args, "install_mode", None) or "source")
|
|
2380
2457
|
checkouts = _parse_peer_checkout_overrides(getattr(args, "peer_checkout", None))
|
|
2458
|
+
exec_commands = _parse_peer_exec_overrides(getattr(args, "peer_exec", None))
|
|
2381
2459
|
project: str | None = None
|
|
2382
2460
|
if install_mode == "checkout":
|
|
2383
2461
|
if not runtime.rosotacom_config:
|
|
@@ -2385,10 +2463,12 @@ def _resolve_ota_smoke_context(
|
|
|
2385
2463
|
local_checkout, project = _ota_checkout_project_path(runtime.rosotacom_config)
|
|
2386
2464
|
for name, path in sorted(checkouts.items()):
|
|
2387
2465
|
binding = bindings.get(name)
|
|
2388
|
-
|
|
2466
|
+
remote = binding is not None and (binding.ssh or name in exec_commands)
|
|
2467
|
+
if binding is not None and not remote and Path(path).resolve() != local_checkout:
|
|
2389
2468
|
raise RuntimeError(
|
|
2390
2469
|
f"--peer-checkout {name}={path} names the peer that runs on this machine, but the active "
|
|
2391
|
-
f"project lives in {local_checkout}. Point it there, or give that peer
|
|
2470
|
+
f"project lives in {local_checkout}. Point it there, or give that peer a transport "
|
|
2471
|
+
"(--peer-ssh or --peer-exec)."
|
|
2392
2472
|
)
|
|
2393
2473
|
plan = _ota_plan_from_bindings(
|
|
2394
2474
|
bindings,
|
|
@@ -2397,6 +2477,7 @@ def _resolve_ota_smoke_context(
|
|
|
2397
2477
|
install_pin=getattr(args, "install_pin", None),
|
|
2398
2478
|
checkouts=checkouts,
|
|
2399
2479
|
project=project,
|
|
2480
|
+
exec_commands=exec_commands,
|
|
2400
2481
|
)
|
|
2401
2482
|
plan_peers = set(plan.peers)
|
|
2402
2483
|
target_peers = set(_peer_keys_from_cfg(target.cfg))
|
|
@@ -2428,7 +2509,7 @@ def _ota_network_sudo_passwords(
|
|
|
2428
2509
|
return {peer.name: "" for peer in plan.peers.values()}
|
|
2429
2510
|
passwords: dict[str, str] = {}
|
|
2430
2511
|
for peer in plan.peers.values():
|
|
2431
|
-
target = peer
|
|
2512
|
+
target = _ota_peer_target(peer)
|
|
2432
2513
|
passwords[peer.name] = getpass.getpass(f"sudo password for {peer.name} ({target}) [network shaping only]: ")
|
|
2433
2514
|
return passwords
|
|
2434
2515
|
|
|
@@ -2528,8 +2609,8 @@ def _ota_preflight(
|
|
|
2528
2609
|
sudo_mode = _validate_ota_sudo_mode(sudo_mode)
|
|
2529
2610
|
sudo_passwords = sudo_passwords or {}
|
|
2530
2611
|
for peer in plan.peers.values():
|
|
2531
|
-
if peer
|
|
2532
|
-
_ota_run(peer, "true", label=f"{peer.name}:
|
|
2612
|
+
if _ota_peer_is_remote(peer):
|
|
2613
|
+
_ota_run(peer, "true", label=f"{peer.name}: reachable", dry_run=dry_run, batch=True)
|
|
2533
2614
|
required = ["python3", "docker", "tar"]
|
|
2534
2615
|
if require_tmux:
|
|
2535
2616
|
required.append("tmux")
|
|
@@ -2634,6 +2715,12 @@ def _ota_stage_tree(peer: OtaSmokePeer, source: Path, destination: str, *, dry_r
|
|
|
2634
2715
|
"-",
|
|
2635
2716
|
".",
|
|
2636
2717
|
]
|
|
2718
|
+
# Reached only in the staging install modes, which `--peer-exec` refuses.
|
|
2719
|
+
# Kept as a check rather than a comment because the failure it prevents is
|
|
2720
|
+
# silent: the local branch below would copy the peer's tree onto the
|
|
2721
|
+
# orchestrator and report success.
|
|
2722
|
+
if peer.exec_command:
|
|
2723
|
+
raise RuntimeError(f"Cannot stage files to {peer.name} over a command transport; use --install-mode checkout.")
|
|
2637
2724
|
if not peer.ssh:
|
|
2638
2725
|
print(f"+ {label}: copy {source} -> {destination}")
|
|
2639
2726
|
if not dry_run:
|
|
@@ -2655,7 +2742,13 @@ def _ota_stage_tree(peer: OtaSmokePeer, source: Path, destination: str, *, dry_r
|
|
|
2655
2742
|
|
|
2656
2743
|
|
|
2657
2744
|
def _ota_stage_text(peer: OtaSmokePeer, text: str, destination: str, *, dry_run: bool, label: str) -> None:
|
|
2658
|
-
|
|
2745
|
+
# Reached only in the staging install modes, which `--peer-exec` refuses.
|
|
2746
|
+
# Kept as a check rather than a comment because the failure it prevents is
|
|
2747
|
+
# silent: the local branch below would copy the peer's tree onto the
|
|
2748
|
+
# orchestrator and report success.
|
|
2749
|
+
if peer.exec_command:
|
|
2750
|
+
raise RuntimeError(f"Cannot stage files to {peer.name} over a command transport; use --install-mode checkout.")
|
|
2751
|
+
print(f"+ {label}: write {destination} on {_ota_peer_target(peer)}")
|
|
2659
2752
|
if dry_run:
|
|
2660
2753
|
return
|
|
2661
2754
|
if peer.ssh:
|
|
@@ -3198,7 +3291,7 @@ def _ota_verify_isolation(
|
|
|
3198
3291
|
published = _ota_run(source, publish, label=f"{source_name}: publish isolation probe", dry_run=dry_run, check=False)
|
|
3199
3292
|
if published.returncode != 0:
|
|
3200
3293
|
_ota_print_failure_output(f"{source_name}: publish isolation probe", published)
|
|
3201
|
-
errors.append(f"{source_name}: isolation probe
|
|
3294
|
+
errors.append(f"{source_name}: isolation probe did not advertise (probe-publish output above names the cause)")
|
|
3202
3295
|
return errors
|
|
3203
3296
|
_print_completed_output(published)
|
|
3204
3297
|
check = _ota_rosotacom_command(plan, _ota_probe_check_parts(target, receiver_name, peer_args), receiver)
|
|
@@ -6332,8 +6425,17 @@ def _stop_smoke_topic_publishers(containers: dict[str, str], specs: list[SmokeTo
|
|
|
6332
6425
|
)
|
|
6333
6426
|
|
|
6334
6427
|
|
|
6428
|
+
# How long the graph may take to report the probe publisher. A loaded graph
|
|
6429
|
+
# (e.g. a control centre with hundreds of topics) can take well over the old
|
|
6430
|
+
# fixed 10 s to discover a new publisher, and that delay is not a defect.
|
|
6431
|
+
_PROBE_ADVERTISE_TIMEOUT_S = 60.0
|
|
6432
|
+
# The probe must outlive the advertise wait plus the peer's absence check, or
|
|
6433
|
+
# the absence check passes trivially against an already-stopped publisher.
|
|
6434
|
+
_PROBE_DURATION_S = 120.0
|
|
6435
|
+
|
|
6436
|
+
|
|
6335
6437
|
def _publish_isolation_probe(
|
|
6336
|
-
container_name: str, ros_setup: str, topic: str, *, rate: float = 5.0, duration: float =
|
|
6438
|
+
container_name: str, ros_setup: str, topic: str, *, rate: float = 5.0, duration: float = _PROBE_DURATION_S
|
|
6337
6439
|
) -> None:
|
|
6338
6440
|
"""Publish a local-only topic in the container's local application domain,
|
|
6339
6441
|
detached, for `duration` seconds (self-stops via `timeout`)."""
|
|
@@ -6362,6 +6464,45 @@ def _topic_present(container_name: str, ros_setup: str, topic: str) -> bool:
|
|
|
6362
6464
|
return topic in names
|
|
6363
6465
|
|
|
6364
6466
|
|
|
6467
|
+
def _isolation_probe_running(container_name: str, topic: str) -> bool:
|
|
6468
|
+
"""Whether the probe publisher for `topic` is still alive in the container."""
|
|
6469
|
+
result = subprocess.run(
|
|
6470
|
+
["docker", "exec", container_name, "pgrep", "-f", f"ros2 topic pub {topic}"],
|
|
6471
|
+
capture_output=True,
|
|
6472
|
+
text=True,
|
|
6473
|
+
check=False,
|
|
6474
|
+
)
|
|
6475
|
+
return result.returncode == 0
|
|
6476
|
+
|
|
6477
|
+
|
|
6478
|
+
def _wait_for_probe_advertisement(
|
|
6479
|
+
container_name: str,
|
|
6480
|
+
ros_setup: str,
|
|
6481
|
+
topic: str,
|
|
6482
|
+
*,
|
|
6483
|
+
timeout_s: float,
|
|
6484
|
+
log_line: Callable[[str], None] | None = None,
|
|
6485
|
+
) -> str:
|
|
6486
|
+
"""Poll until `topic` is reported by the container's local graph.
|
|
6487
|
+
|
|
6488
|
+
Returns "advertised", "publisher-gone" (the probe process exited or never
|
|
6489
|
+
started), or "timeout" (the publisher is alive but the graph did not report
|
|
6490
|
+
the topic within `timeout_s`). Only "publisher-gone" points at a publisher
|
|
6491
|
+
defect; a loaded graph reports late, which is what "timeout" captures.
|
|
6492
|
+
"""
|
|
6493
|
+
deadline = time.monotonic() + timeout_s
|
|
6494
|
+
while True:
|
|
6495
|
+
if log_line is not None:
|
|
6496
|
+
log_line(f"Waiting for isolation probe {topic} to advertise in {container_name}")
|
|
6497
|
+
if _topic_present(container_name, ros_setup, topic):
|
|
6498
|
+
return "advertised"
|
|
6499
|
+
if not _isolation_probe_running(container_name, topic):
|
|
6500
|
+
return "publisher-gone"
|
|
6501
|
+
if time.monotonic() >= deadline:
|
|
6502
|
+
return "timeout"
|
|
6503
|
+
time.sleep(1)
|
|
6504
|
+
|
|
6505
|
+
|
|
6365
6506
|
def _verify_isolation(
|
|
6366
6507
|
pub_container: str,
|
|
6367
6508
|
pub_setup: str,
|
|
@@ -6376,15 +6517,18 @@ def _verify_isolation(
|
|
|
6376
6517
|
log_line(f"Starting isolation probe {topic} in {pub_container}")
|
|
6377
6518
|
_publish_isolation_probe(pub_container, pub_setup, topic)
|
|
6378
6519
|
try:
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
if
|
|
6387
|
-
return [
|
|
6520
|
+
outcome = _wait_for_probe_advertisement(
|
|
6521
|
+
pub_container, pub_setup, topic, timeout_s=_PROBE_ADVERTISE_TIMEOUT_S, log_line=log_line
|
|
6522
|
+
)
|
|
6523
|
+
if outcome == "publisher-gone":
|
|
6524
|
+
return [
|
|
6525
|
+
f"isolation check inconclusive: probe publisher for {topic} exited or never started in {pub_container}"
|
|
6526
|
+
]
|
|
6527
|
+
if outcome == "timeout":
|
|
6528
|
+
return [
|
|
6529
|
+
f"isolation check inconclusive: probe publisher for {topic} is running in {pub_container} "
|
|
6530
|
+
f"but the graph did not report it within {_PROBE_ADVERTISE_TIMEOUT_S:.0f}s"
|
|
6531
|
+
]
|
|
6388
6532
|
log_line(f"Checking that isolation probe {topic} is absent in {check_container}")
|
|
6389
6533
|
if _topic_present(check_container, check_setup, topic):
|
|
6390
6534
|
return [f"isolation breach: {topic} from {pub_container} leaked to {check_container}"]
|
|
@@ -6516,12 +6660,32 @@ def probe_publish_command(args: argparse.Namespace) -> int:
|
|
|
6516
6660
|
# Block until the topic is actually advertised so a caller's subsequent
|
|
6517
6661
|
# absence check on the other peer is meaningful (not a false pass on a
|
|
6518
6662
|
# publisher that never came up).
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6663
|
+
started = time.monotonic()
|
|
6664
|
+
outcome = _wait_for_probe_advertisement(container, ros_setup, args.topic, timeout_s=args.advertise_timeout)
|
|
6665
|
+
if outcome == "advertised":
|
|
6666
|
+
print(f"Publishing {args.topic} in {container} (identity {args.identity}); advertised.")
|
|
6667
|
+
return 0
|
|
6668
|
+
if outcome == "publisher-gone":
|
|
6669
|
+
if time.monotonic() - started >= args.duration:
|
|
6670
|
+
print(
|
|
6671
|
+
f"ERROR: probe publisher for {args.topic} in {container} (identity {args.identity}) ran its "
|
|
6672
|
+
f"{args.duration:.0f}s --duration without the graph reporting the topic; keep --duration "
|
|
6673
|
+
f"above --advertise-timeout",
|
|
6674
|
+
file=sys.stderr,
|
|
6675
|
+
)
|
|
6676
|
+
else:
|
|
6677
|
+
print(
|
|
6678
|
+
f"ERROR: probe publisher for {args.topic} exited or never started in {container} "
|
|
6679
|
+
f"(identity {args.identity})",
|
|
6680
|
+
file=sys.stderr,
|
|
6681
|
+
)
|
|
6682
|
+
else:
|
|
6683
|
+
print(
|
|
6684
|
+
f"ERROR: probe publisher for {args.topic} is running in {container} (identity {args.identity}) "
|
|
6685
|
+
f"but the graph did not report it within {args.advertise_timeout:.0f}s; a loaded graph reports "
|
|
6686
|
+
f"late, retry with a larger --advertise-timeout",
|
|
6687
|
+
file=sys.stderr,
|
|
6688
|
+
)
|
|
6525
6689
|
return 1
|
|
6526
6690
|
|
|
6527
6691
|
|
|
@@ -8495,6 +8659,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
8495
8659
|
"Required for every peer in that mode; the same repository is at a different path on each machine."
|
|
8496
8660
|
),
|
|
8497
8661
|
)
|
|
8662
|
+
ota_smoke_parser.add_argument(
|
|
8663
|
+
"--peer-exec",
|
|
8664
|
+
action="append",
|
|
8665
|
+
default=[],
|
|
8666
|
+
metavar="PEER=COMMAND",
|
|
8667
|
+
help=(
|
|
8668
|
+
"Run this peer's commands through COMMAND instead of ssh; the script is appended as the final "
|
|
8669
|
+
"argument, the same contract ssh has. For --install-mode checkout only, and mutually exclusive "
|
|
8670
|
+
"with --peer-ssh for the same peer. Use it to put a peer behind a transport narrower than a "
|
|
8671
|
+
"shell, such as a forced command that accepts only this project's own commands."
|
|
8672
|
+
),
|
|
8673
|
+
)
|
|
8498
8674
|
ota_smoke_parser.add_argument("--target-type", choices=["auto", "session", "scenario"], default="auto")
|
|
8499
8675
|
ota_smoke_parser.add_argument("--interactive", action="store_true", help="Open a local control tmux UI.")
|
|
8500
8676
|
ota_smoke_parser.add_argument("--stop", action="store_true", help="Stop an OTA smoke run.")
|
|
@@ -8957,7 +9133,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
8957
9133
|
probe_publish_parser.add_argument("--instance-id")
|
|
8958
9134
|
probe_publish_parser.add_argument("--topic", default=ISOLATION_PROBE_TOPIC)
|
|
8959
9135
|
probe_publish_parser.add_argument("--rate", type=float, default=5.0)
|
|
8960
|
-
probe_publish_parser.add_argument("--duration", type=float, default=
|
|
9136
|
+
probe_publish_parser.add_argument("--duration", type=float, default=_PROBE_DURATION_S)
|
|
9137
|
+
probe_publish_parser.add_argument(
|
|
9138
|
+
"--advertise-timeout",
|
|
9139
|
+
type=float,
|
|
9140
|
+
default=_PROBE_ADVERTISE_TIMEOUT_S,
|
|
9141
|
+
help="Seconds to wait for the local graph to report the probe topic before failing.",
|
|
9142
|
+
)
|
|
8961
9143
|
probe_publish_parser.add_argument(
|
|
8962
9144
|
"--stop", action="store_true", help="Stop a running probe publisher instead of starting one."
|
|
8963
9145
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev10
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -494,6 +494,34 @@ in this mode — there is no staging to undo, and the workdir is your repository
|
|
|
494
494
|
The run manifest records which mode and which version the peers ran, so a result
|
|
495
495
|
can be attributed to an artefact rather than to a working copy.
|
|
496
496
|
|
|
497
|
+
#### How the peers are reached: `--peer-exec`
|
|
498
|
+
|
|
499
|
+
`--peer-ssh` gives the orchestrator a shell on the peer, which is more than a
|
|
500
|
+
run needs and more than some machines should hand out. `--peer-exec` names the
|
|
501
|
+
transport instead:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
505
|
+
--install-mode checkout \
|
|
506
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt \
|
|
507
|
+
--peer-exec b='remote-rosotacom robot'
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The command is run with the script as its final argument — the contract
|
|
511
|
+
`ssh host <script>` already has — so anything of that shape can carry a peer: a
|
|
512
|
+
wrapper that logs what a run asks for, a container exec, or a forced command
|
|
513
|
+
that accepts some scripts and refuses the rest. rosotacom does not know or care
|
|
514
|
+
which; it only stops assuming that reaching a peer means having a shell on it.
|
|
515
|
+
|
|
516
|
+
Two restrictions, both load-bearing. It applies to `--install-mode checkout`
|
|
517
|
+
only, because the staging modes push a tar stream and a file write by taking
|
|
518
|
+
the ssh client's own argv apart, and a transport that promises no more than
|
|
519
|
+
"run this script" cannot carry them. And a peer takes either `--peer-ssh` or
|
|
520
|
+
`--peer-exec`, never both: leaving it ambiguous hides which one carried the run.
|
|
521
|
+
|
|
522
|
+
`-t` and `-o BatchMode=yes` are dropped rather than forwarded. They are options
|
|
523
|
+
of one client, and a transport that is not ssh never agreed to understand them.
|
|
524
|
+
|
|
497
525
|
### Live status / debugging overview
|
|
498
526
|
|
|
499
527
|
Enable a continuously-updated, per-topic pipeline overview by setting
|