Repository navigation
fix(ansible): keep autoware_data owned by the user - #7260
Merged
xmfcx merged 5 commits intoAug 7, 2026
Merged
Conversation
autoware_data sits in the home directory of the user because every consumer reads it as that user: the ansible roles, the ROS nodes that write TensorRT engine files next to the models, and the containers under docker/, which mount it for the unprivileged aw user. Older Dockerfiles installed as root, and the download tasks in this repository used become: true, so many installs hold model files and one model directory that root owns. A directory that root owns stops all three consumers. Add the role autoware_data_ownership, which gives the tree to the user that runs the playbook. It does nothing when the directory is absent, and nothing when the user already owns every path, so only a repair needs sudo. Make artifacts and demo_artifacts depend on it, so the tree is user-owned before any task writes into it. Remove become: true from every task that writes into autoware_data: 16 in artifacts and 3 in demo_artifacts. One of the 16 is the task that created the root-owned diffusion_planner/v3.1 directory. Install unzip keeps become: true, because apt needs it. Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
Contributor
|
Thank you for contributing to the Autoware project! 🚧 If your pull request is in progress, switch it to draft mode. Please ensure:
|
The repair used ansible.builtin.file with recurse: true. That module follows a symbolic link during the walk, so a link inside the tree let the repair chown its target outside ~/autoware_data, as root. The guard used ansible.builtin.find, which does not follow links, so it could not see the paths the repair would write. Resolve the directory with readlink -f, then let the guard and the repair act on that one real path. Both keep the default link behaviour, so they read and write the same set of paths, and a corrected tree stops the guard. The guard also no longer triggers on the skipped_paths of find, which is set for a vanished file or a path that is not a directory, not only for a directory that cannot be read. Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
A bind mount in the short syntax defaults to create_host_path: true. When a path under ~/autoware_data is missing, the daemon creates it as root, and the unprivileged aw user in the container cannot write it. The container still starts, so the run fails later with a message about the data rather than the mount, and the user cannot remove the new directories without sudo. No ansible role creates ~/autoware_data/scenarios, so that path was root-owned even after a complete install. Move all 17 autoware_data mounts to the long syntax with create_host_path: false. Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
The path filter listed ansible/roles/artifacts/** only, so a change confined to ansible/roles/autoware_data_ownership/** selected no files and the health check did not run. That role runs as a dependency of artifacts, so the same job exercises it. Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
xmfcx
marked this pull request as ready for review
August 7, 2026 10:21
xmfcx
requested review from
isamu-takagi,
mitsudome-r,
oguzkaganozt and
youtalk
as code owners
August 7, 2026 10:21
mitsudome-r
approved these changes
Aug 7, 2026
mitsudome-r
left a comment
Member
There was a problem hiding this comment.
Confirmed that the PR works on my local machine.
xmfcx
enabled auto-merge (squash)
August 7, 2026 11:06
xmfcx
added a commit
to xmfcx/autoware
that referenced
this pull request
Aug 8, 2026
…Face Batch E is the last batch of the artifact hosting migration. It removes the 15 pinned get_url tasks and the 7 directory tasks around them. Five hf download tasks take their place, and each one is pinned to a tag. The same 15 files land at the same paths, so the launch files need no change. The 10 onnx files match the removed pins through the LFS oid of each tag. The 5 param.json files are too small for LFS, and a direct download from each tag gives the same 5 hashes. Every get_url task that this batch removes ran with become: true, so an install made before the migration holds model files that root owns. hf runs as the user that runs the playbook, and it cannot write into a root-owned directory. The autoware_data_ownership role corrects such an install, and the artifacts role already depends on it. - Ownership role: autowarefoundation#7260 Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
xmfcx
added a commit
that referenced
this pull request
Aug 9, 2026
…Face (#7258) Batch E is the last batch of the artifact hosting migration. It removes the 15 pinned get_url tasks and the 7 directory tasks around them. Five hf download tasks take their place, and each one is pinned to a tag. The same 15 files land at the same paths, so the launch files need no change. The 10 onnx files match the removed pins through the LFS oid of each tag. The 5 param.json files are too small for LFS, and a direct download from each tag gives the same 5 hashes. Every get_url task that this batch removes ran with become: true, so an install made before the migration holds model files that root owns. hf runs as the user that runs the playbook, and it cannot write into a root-owned directory. The autoware_data_ownership role corrects such an install, and the artifacts role already depends on it. - Ownership role: #7260 Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
4 of 5 tasks
TomcoGame
pushed a commit
to TomcoGame/Autoware-Assurance-Stack
that referenced
this pull request
Oct 25, 2026
…n#7260) Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
TomcoGame
pushed a commit
to TomcoGame/Autoware-Assurance-Stack
that referenced
this pull request
Oct 25, 2026
…Face (autowarefoundation#7258) Batch E is the last batch of the artifact hosting migration. It removes the 15 pinned get_url tasks and the 7 directory tasks around them. Five hf download tasks take their place, and each one is pinned to a tag. The same 15 files land at the same paths, so the launch files need no change. The 10 onnx files match the removed pins through the LFS oid of each tag. The 5 param.json files are too small for LFS, and a direct download from each tag gives the same 5 hashes. Every get_url task that this batch removes ran with become: true, so an install made before the migration holds model files that root owns. hf runs as the user that runs the playbook, and it cannot write into a root-owned directory. The autoware_data_ownership role corrects such an install, and the artifacts role already depends on it. - Ownership role: autowarefoundation#7260 Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
~/autoware_datasits in the home directory of the user because every consumer reads it as that user:docker/, which mount it for the unprivilegedawuserThe directory was never meant to hold a path that root owns. A path that root owns stops all three consumers above.
Two things in this repository create such a path.
The download tasks used
become: true, so many installs hold model files and one model directory that root owns. Older Dockerfiles also installed as root.The compose files under
docker/used the short mount syntax. That syntax creates a missing host path, and the Docker daemon creates it as root. A user who starts a demo before the ansible run therefore gets the same problem on a clean machine.The container still starts in that state. Autoware then reads an empty
mapsdirectory and an emptyml_modelsdirectory. The run fails later with a message about the data, not about the mount. The user also cannot remove the new directories without sudo.This PR removes both causes, and corrects the installs that already have the problem.
What changes
A new role,
autoware_data_ownership. It gives~/autoware_dataand every path under it to the user that runs the playbook. It does nothing when the directory does not exist, and nothing when the user already owns every path. Only the correction needs sudo, so a clean install needs no password.The artifacts health check now also runs when this role changes. Its path filter listed
ansible/roles/artifacts/**only, so a change to the new role alone got no coverage.artifactsanddemo_artifactsdepend on the new role. A role dependency runs before the role that declares it, so the tree is user-owned before any task writes into it. The dependency inherits the tags of its parent, so it runs under--tags artifactsand under--tags demo_artifacts. Ansible runs it once per host even when both parents are selected, so--list-tasksprints it under both parents but only one run happens.No task writes into
~/autoware_dataas root any more. This removesbecome: truefrom 16 tasks inartifactsand from 3 tasks indemo_artifacts. TheInstall unziptask indemo_artifactskeepsbecome: true, because apt needs it.One of the 16 is the task
Create diffusion_planner/v3.1 directory. That task is the reason a directory that root owns exists at all. Every other directory task in the role was already correct.Compose stops instead of creating a mount source. Every bind mount of
~/autoware_dataunderdocker/moves to the long syntax withcreate_host_path: false. Compose then stops withbind source path does not existwhen a path is missing, and it no longer creates that path as root. This changes 17 mounts in 9 files.No ansible role creates
~/autoware_data/scenarios, so that path was root-owned even after a complete install. The three devcontainers already create~/autoware_dataon the host with theirinitializeCommand, so that flow does not change.This is a change of behaviour for a user who has not run the ansible roles. That user now reads a clear error, instead of a run that breaks later with an empty directory. The demo READMEs already list these paths as prerequisites.
docker/examples/basic/README.mdhad no such list, and this PR adds one.How the role decides to run
The role resolves
~/autoware_datawithreadlink -f. It then looks for the first path under the resolved directory that the user does not own. The correction runs only when that search prints a path.findandchownboth keep the default behaviour for a symbolic link. They act on the link itself, and they do not descend into it. Two results follow from this. A link that points out of~/autoware_datakeeps the owner of its target. The search and the correction also read and write one set of paths, so a corrected tree stops the search.readlink -fresolves the directory when it sits on another disk behind a symbolic link. The role corrects the real directory in that case. When the path cannot be resolved,readlink -fprints nothing and the role does nothing.How to verify manually
1. Check out the branch
2. Look at the paths that root owns
3. Run the playbook
On an install made before this PR, the task
Take ownership of the Autoware data directoryreportschanged. On a clean install it reportsskipped, and the run needs no password.4. Look again
The command must print nothing. A second run of the playbook skips the correction.
5. Check that Compose no longer creates a mount source
A throwaway
HOMEgives the compose file an empty tree to mount, so this check leaves the real~/autoware_dataalone.HOME=$(mktemp -d) docker compose -f docker/examples/basic/dev-cpu.compose.yaml upCompose must stop with
bind source path does not exist, and it must create no directory under the temporary tree. Before this PR it created that path as root.Compose pulls the image of the demo first when the machine does not hold it yet, which takes several GB.
Relation to the Hugging Face migration
Batch E carried a smaller form of this correction, scoped to the artifacts directory. This PR replaces it, so batch E drops those two tasks and rebases on this one. Batch E also deletes 15 of the 16 tasks that lose
become: truehere, so the rebase resolves in favor of the deletion.AI usage
AI usage: written with Claude Code, from a review of batch E, then corrected twice from a review of this branch

Self-review:
Verification: the role and the compose change both ran on Ubuntu 24.04. The planning simulator demo drove to a goal with the compose file from this PR.
What ran, and what did not
Versions
ansible/scripts/install-ansible.shpinsubuntu:24.04The role, on the host
Six inputs skip the correction, and none asks for a password:
The real
~/autoware_dataof the host also skips. A run with--checkalso skips.The role, end to end in a container
A container of
ubuntu:24.04with passwordless sudo ran the final role against a tree that root owns.changed=1, and made every path user-ownedhfand the TensorRT engine writer needsudo -k, the second run reportedchanged=0andskipped=1The same container ran the role against two trees that hold a symbolic link.
~/autoware_datais itself a symbolic link, the correction fixed the resolved directory and its contentsSeven shell fixtures measured the guard and the correction against the GNU tools directly.
The compose files
docker compose configaccepts all nine changed files. The resolved configuration shows 17autoware_datamounts, each withcreate_host_path: false. Two of them keepread_only: true, which matches the two:romounts before the change.Three tests ran against
docker/examples/basic/dev-cpu.compose.yaml, with the imageghcr.io/autowarefoundation/autoware:universe-devel-jazzy. Each one used a throwawayHOME, so the real~/autoware_datastayed out of the test.bind source path does not exist, and created nothingautoware_data,autoware_data/mapsandautoware_data/ml_modelsasroot:root, andrmthen refused to remove themid -uas 1000The planning simulator demo
docker/examples/demos/planning-simulator/docker-compose.yamlran with the imageghcr.io/autowarefoundation/autoware:universe-jazzy. Bothautoware_datamounts in that file carry the long syntax from this PR.sample-map-planningthrough the mount, as the unprivilegedawuser/api/routing/statethen reported3, which is ARRIVEDThe tree of this host is already user-owned, so the correction skipped during this run.
Not checked
artifactsordemo_artifactsthat downloads a real artifact~/autoware_datainstead of two directories under it