You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.7 KiB
YAML
170 lines
4.7 KiB
YAML
---
|
|
- name: Ensure multipass is installed and create a VM with cloud-init
|
|
hosts: localhost
|
|
gather_facts: yes
|
|
vars_prompt:
|
|
- name: vm_name
|
|
prompt: "What is the VM name (don't use spaces)?"
|
|
private: no
|
|
default: testvm
|
|
vars:
|
|
vm_image: 24.04
|
|
vm_disk: 15G
|
|
vm_memory: 4G
|
|
vm_cpus: 1
|
|
ssh_key_name: "{{ vm_name }}_ssh_key"
|
|
|
|
tasks:
|
|
- name: Check if VM already exists
|
|
command: multipass list --format json
|
|
register: vm_list_json
|
|
|
|
- name: Parse VM list
|
|
set_fact:
|
|
vm_exists: "{{ vm_name in ((vm_list_json.stdout | from_json).list | map(attribute='name') | list) }}"
|
|
|
|
- name: Output message if VM already exists
|
|
debug:
|
|
msg: "VM with name '{{ vm_name }}' already exists. No action will be taken."
|
|
when: vm_exists
|
|
|
|
- name: Gather OS facts
|
|
setup:
|
|
filter: "ansible_distribution"
|
|
when: not vm_exists
|
|
|
|
- name: Detect OS
|
|
set_fact:
|
|
os_type: "{{ ansible_facts['distribution'] }}"
|
|
|
|
- name: Check if Homebrew is installed (macOS)
|
|
command: brew --version
|
|
register: homebrew_check
|
|
ignore_errors: yes
|
|
when: os_type == "MacOSX" and not vm_exists
|
|
|
|
- name: Install Homebrew (macOS)
|
|
shell: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
when: os_type == "MacOSX" and homebrew_check.failed and not vm_exists
|
|
|
|
- name: Check if multipass is installed
|
|
shell: "command -v multipass || echo 'not found'"
|
|
register: multipass_check
|
|
changed_when: false
|
|
|
|
- name: Install multipass using Homebrew (macOS)
|
|
homebrew:
|
|
name: multipass
|
|
state: present
|
|
when:
|
|
- os_type == "MacOSX"
|
|
- multipass_check.stdout == "not found"
|
|
- not vm_exists
|
|
|
|
- name: Install multipass using snap (Ubuntu)
|
|
snap:
|
|
name: multipass
|
|
state: present
|
|
when:
|
|
- os_type == "Ubuntu"
|
|
- multipass_check.stdout == "not found"
|
|
- not vm_exists
|
|
|
|
- name: Generate SSH key pair
|
|
command: ssh-keygen -t rsa -b 2048 -f ./{{ ssh_key_name }} -N "" -C "ubuntu"
|
|
args:
|
|
creates: ./{{ ssh_key_name }}
|
|
when: not vm_exists
|
|
|
|
- name: Read the public SSH key
|
|
command: cat ./{{ ssh_key_name }}.pub
|
|
register: ssh_public_key
|
|
when: not vm_exists
|
|
|
|
- name: Create cloud-init.yaml file
|
|
copy:
|
|
dest: ./cloud-init.yaml
|
|
content: |
|
|
## cloud-init
|
|
|
|
users:
|
|
- name: ubuntu
|
|
ssh-authorized-keys:
|
|
- {{ ssh_public_key.stdout }}
|
|
sudo: ['ALL=(ALL) NOPASSWD:ALL']
|
|
groups: sudo
|
|
shell: /bin/bash
|
|
|
|
package_update: true
|
|
packages:
|
|
- python3-pip
|
|
- python3
|
|
- python-is-python3
|
|
- python3-venv
|
|
|
|
hostname: {{ vm_name }}
|
|
fqdn: {{ vm_name }}.local
|
|
|
|
final_message: "The instance is now up for $UPTIME seconds"
|
|
when: not vm_exists
|
|
|
|
- name: Verify cloud-init.yaml file exists
|
|
stat:
|
|
path: ./cloud-init.yaml
|
|
register: cloud_init_file
|
|
when: not vm_exists
|
|
|
|
- name: Fail if cloud-init.yaml does not exist
|
|
fail:
|
|
msg: "cloud-init.yaml file does not exist"
|
|
when:
|
|
- not vm_exists
|
|
- cloud_init_file is defined
|
|
- not cloud_init_file.stat.exists | default(false)
|
|
|
|
- name: Launch VM with multipass
|
|
command: multipass launch {{ vm_image }} --name {{ vm_name }} --disk {{ vm_disk }} -m {{ vm_memory }} --cloud-init ./cloud-init.yaml
|
|
register: vm_launch
|
|
when: not vm_exists
|
|
|
|
- name: Get VM info
|
|
command: multipass info {{ vm_name }} --format json
|
|
register: vm_info_json
|
|
when: not vm_exists
|
|
|
|
- name: Parse VM IP address
|
|
set_fact:
|
|
vm_ip: "{{ (vm_info_json.stdout | from_json).info[vm_name].ipv4[0] }}"
|
|
when: not vm_exists
|
|
|
|
- name: Generate inventory file
|
|
copy:
|
|
dest: ./inventory.yml
|
|
content: |
|
|
all:
|
|
hosts:
|
|
{{ vm_name }}:
|
|
ansible_host: {{ vm_ip }}
|
|
ansible_python_interpreter: /usr/bin/python3
|
|
vars:
|
|
ansible_user: ubuntu
|
|
ansible_ssh_private_key_file: ./{{ ssh_key_name }}
|
|
when: not vm_exists
|
|
|
|
- name: Add VM hostname to local /etc/hosts
|
|
become: yes
|
|
lineinfile:
|
|
path: /etc/hosts
|
|
line: "{{ vm_ip }} {{ vm_name }}.local"
|
|
state: present
|
|
when: not vm_exists
|
|
|
|
- name: Wait for VM to be ready
|
|
wait_for:
|
|
host: "{{ vm_ip }}"
|
|
port: 22
|
|
delay: 10
|
|
timeout: 300
|
|
when: not vm_exists
|
|
|