How to test a cloud-init file locally?
The most straight forward choice seems to be VirtualBox and Vagrant.
I will show you how to set up the Vagrant experimental
cloud_init flag to test your cloud-init files on the locally deployed VM.
This way you can quickly validate the expected results without spinning up a real VM inside your cloud provider panel.
TLDR; Clone https://github.com/jmarceli/test-cloud-init-vagrant, adjust the cloud-init-test.yml file, execute the
vagrant up command and check the results with
It will be useful to have at least basic knowledge about the following tools:
- Virtualbox (download and install the latest version from https://www.virtualbox.org/wiki/Downloads)
- Vagrant (download and install the latest version from https://www.vagrantup.com/downloads)
In this tutorial I will be using Ubuntu Server Cloud Images from https://cloud-images.ubuntu.com.
For the Virtualbox an appropriate image with the
.box extension might be https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64-vagrant.box
You don't have to download it manually as this will URL will be included in your Vagrantfile and handled automatically.
Create a directory for this project somewhere in your local filesystem e.g. ~/cloud-init-tests/. Then create a Vagrantfile inside that directory. This file will contain all the required configuration:
Vagrant.configure("2") do |config| config.env.enable # enable .env support plugin (it will let us easily enable cloud_init support) # Give a custom name for a VM created by this script for a Vagrant CLI config.vm.define "focal-server-cloudimg-amd64-vagrant" # Name for the box image downloaded from the box_url # it will be used to create a folder inside ~/.vagrant.d/boxes to avoid re-downloading config.vm.box = "focal-server-cloudimg-amd64-vagrant" # URL used as a source for the vm.box defined above config.vm.box_url = "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64-vagrant.box" config.vm.provider "virtualbox" do |v| # Name visible inside your Virtualbox UI v.name = "cloud-init-ubuntu-test" end # cloud-init script config.vm.cloud_init do |cloud_init| # With Ubuntu cloud images you have to use cloud_init to get an access cloud_init.content_type = "text/cloud-config" cloud_init.path = "cloud-init-test.yml" end end
Vagrant experimental flags
The next file which has to be created is .env. It should be placed in the same directory as your Vagrantfile. Content of the .env file should be as follows:
Together with previously mentioned line
config.env.enable this will enable cloud_init and disks experimental flags.
cloud_init will NOT work without a disks flag, so this is very important to enable both of them. What is strange this information is not currently provided on the Vagrant docs pages.
Tested cloud-init file
The last but not least, your cloud-init file which in my example is named cloud-init-test.yml.
It can have any content supported by the cloud-init and in my example, it will be a
yml file with the following lines:
packages: - python-is-python3 users: - name: test_user_unique_name groups: sudo homedir: /custom/home/dir shell: /bin/bash sudo: ["ALL=(ALL) NOPASSWD:ALL"] # ssh-authorized-keys: # - ssh-rsa USE_YOUR_RSA_KEY_HERE_IF_NEEDED
Executing the test
Now it is time to test the setup.
vagrant up inside the folder where you placed the Vagrantfile.
If you set everything properly the following output should appear:
==> vagrant: You have requested to enabled the experimental flag with the following features: ==> vagrant: ==> vagrant: Features: cloud_init, disks ==> vagrant: ==> vagrant: Please use with caution, as some of the features may not be fully ==> vagrant: functional yet. Bringing machine 'focal-server-cloudimg-amd64-vagrant' up with 'virtualbox' provider... ==> focal-server-cloudimg-amd64-vagrant: Importing base box 'focal-server-cloudimg-amd64-vagrant'...
After a few seconds (maybe minutes depending on your cloud-init file) your VM should be up and running.
Now you can check the results by executing
In my example it is easy to verify that a user
test_user_unique_name is present by executing
cat /etc/passwords and that a package
python-is-python3 was installed with
python --version (it outputs
After you will finish with the examination of the provisioned VM you can safely destroy it to retrieve all resources allocated for its existence.
Just execute the
vagrant destroy command followed by
y answer to the confirmation question.
https://www.vagrantup.com/docs/cloud-init/usage - official Vagrant docs https://www.vagrantup.com/docs/cloud-init/configuration - different formats of cloud-init supported by Vagrant https://cloudinit.readthedocs.io/en/latest/topics/modules.html - cloud-init modules list https://cloudinit.readthedocs.io/en/latest/topics/examples.html - cloud-init examples