pip upgrade can fail in ansible install
The pip install --upgrade pip in the ansible module, can result in the following:
/usr/bin/python3 -m pip install --break-system-packages --upgrade pip
Requirement already satisfied: pip in /usr/lib/python3/dist-packages (25.0)
Collecting pip
Using cached pip-25.0.1-py3-none-any.whl.metadata (3.7 kB)
Using cached pip-25.0.1-py3-none-any.whl (1.8 MB)
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 25.0
error: uninstall-no-record-file
× Cannot uninstall pip 25.0
╰─> The package's contents are unknown: no RECORD file was found for pip.
hint: The package was installed by debian. You should check if it can uninstall the package.
This will cause the module to exit with exception.
@TheRealFalcon What do you think to do? Catch exception?
@AliyevH , yes I'm thinking that in most cases we shouldn't need pip updated, so we can catch and log the exception.
I created a pull request with the bug fix https://github.com/canonical/cloud-init/pull/6301
Info dump for future first timers (like me):
What this module does
package_name in cc_ansible.py is almost always "ansible" or "ansible-core" (lightweight ansible), see package_name in schema-cloud-config-v1.json . The idea is to install/ either package/ ensure it is installed before pulling playbooks
Also note, that the modules in cloud-init usually run only once (at the first boot of the VM) and not per-boot (you can customize it)
Reproducing the bug:
- This file
/tmp/user-dataon my local will be used later to setup my VM
cat >/tmp/user-data <<EOF
#cloud-config
ansible:
package_name: ansible-core
install_method: pip
pull:
url: "https://github.com/holmanb/vmboot.git"
playbook_name: ubuntu.yml
EOF
-
Spin up a VM witht this config and with the
noble(ubuntu 24) imagemultipass launch noble --name test-vm --cloud-init /tmp/user-data. Note: When I am done with the VM and no longer care about it,multipass delete test-vm --purge -
Inspect the error
multipass exec test-vm -- cloud-init status --long
status: error
extended_status: error - done
boot_status_code: enabled-by-generator
last_update: Thu, 01 Jan 1970 00:01:46 +0000
detail: DataSourceNoCloud [seed=/dev/vda]
errors:
- ('ansible', ProcessExecutionError("Unexpected error while running command.\nCommand: ['/usr/bin/python3', '-m', 'pip', 'install', '--break-system-packages', '--upgrade', 'pip']\nExit code: 1\nReason: -\nStdout: Requirement already satisfied: pip in /usr/lib/python3/dist-packages (24.0)\n Collecting pip\n Downloading pip-25.1.1-py3-none-any.whl.metadata (3.6 kB)\n Downloading pip-25.1.1-py3-none-any.whl (1.8 MB)\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 601.8 kB/s eta 0:00:00\n Installing collected packages: pip\n Attempting uninstall: pip\n Found existing installation: pip 24.0\nStderr: ERROR: Cannot uninstall pip 24.0, RECORD file not found. Hint: The package was installed by debian."))
recoverable_errors:
WARNING:
- Running module ansible (<module 'cloudinit.config.cc_ansible' from '/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py'>) failed
You can alternatively multipass shell test-vm to bash your way around inside the VM. Other log fields that you can look into /var/log/cloud-init-output.log /var/log/cloud-init.log
Testing the local changes
-
This comment discusses how to mount the local repo (before launching the VM) with lxd in order to test the python scripts (the script is used and not a wheel). Note that my change does not affect systemd so no need to build the apt package/ install it then rerun cloud-init with reboot as the comment explains for such cases.
-
I have a Mac and I had problems with lxc so I used
multipassinstead (which does not mount before launching the VM so I will need to rerun cloud-init to check my python script changes) -
multipass launch noble --name test-vm --cloud-init user-data --mount /tmp/cloud-init/cloudinit:/usr/lib/python3/dist-packages/cloudinit- The most important thing to note is that I first dittoed my local repo into
/tmp/cloud-init. This is due to the " Full Disk Access setting" in macOS. If this setting is not enabled for multipassd, then mounting will never be functional (Operation not permitted problems) when you mount for paths that are protected such as~, hence I just moved the local repo to/tmpto save myself the hassle. Even passing--uid-map 501:0 --gid-map 20:0to the multipass command will not fix the issue.
- The most important thing to note is that I first dittoed my local repo into
-
There is a discrepancy between the cloud-init version (25.1.2) in noble and the version in the local repo (25.1.4) . So we need to rerun cloud-init (weirdly the rerun with reboot
sudo cloud-init clean --logs --configs all --rebootz does not work and it still uses the old version while the rerun without reboot works zsudo cloud-init clean --logs && sudo cloud-init init --local && sudo cloud-init init && sudo cloud-init modules --mode=config && sudo cloud-init modules --mode=final)
In the VM, the entry-point bash script /usr/bin/cloud-init was using the old version (25.1.2). My guess is that it is generated when the debian package is built
On the other hand, the python-script code (./cloudinit/version.py in the local repo mounted to /usr/lib/python3/dist-packages/cloudinit/version.py in the VM) points to 25.1.4.
I did not have to edit the versions. It just worked:TM: