Looking deeper, we can see that cmd.main.status_wrapper atomically writes JSON (yay!) to the 'data_d' (/var/lib/cloud/data) then symlinks that status file in the 'link_d' (/run/cloud-init). All seems reasonable, but let's look at how it does that symlinking:
This is non-atomic and entirely possible for readers (such as `--wait`) to see the entry in the FS, before it gets deleted, the deletion to occur and then open it.
Reading the code - https:/ /github. com/canonical/ cloud-init/ blob/main/ cloudinit/ cmd/status. py#L141- L144 - , the status command tries to guard against the file not existing, but clearly this run slipped through - the file existed when we os.path.exists() it, but not when we open() it :|
Looking deeper, we can see that cmd.main. status_ wrapper atomically writes JSON (yay!) to the 'data_d' (/var/lib/ cloud/data) then symlinks that status file in the 'link_d' (/run/cloud-init). All seems reasonable, but let's look at how it does that symlinking:
https:/ /github. com/canonical/ cloud-init/ blob/main/ cloudinit/ cmd/main. py#L755- L758
Note the `force=True`, and refer to the implementation of sym_link:
https:/ /github. com/canonical/ cloud-init/ blob/2837b835f1 01d81704f018a4f 872b1d660eb6f3e /cloudinit/ util.py# L1887-L1891
.. which deletes the symlink, then re-creates it.
This is non-atomic and entirely possible for readers (such as `--wait`) to see the entry in the FS, before it gets deleted, the deletion to occur and then open it.