Skip to content

Instantly share code, notes, and snippets.

@brianonn
Last active December 24, 2022 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianonn/cf8ac0cbd73f56e929cda7fbf80b99c7 to your computer and use it in GitHub Desktop.
Save brianonn/cf8ac0cbd73f56e929cda7fbf80b99c7 to your computer and use it in GitHub Desktop.
for telmate/proxmox provider: extract host IPs from terraform.tfstate file after hosts are created

Extract hosts inventory file for Ansible

This script is intended to be used with the Telmate terraform provider for Proxmox

Requirements

  • Telmate terraform provider installed via terraform init
  • must use tags = "server" or tags = "worker" when defining server and worker VM's in the terraform provider
  • have a successfull terraform apply that created the terraform.tfstate file
  • Ansible installed
  • jq installed

Quick installation instructions:

  1. macOS - brew install jq ansible
  2. Debian/Old Ubuntu - apt install jq ansible
  3. New Ubuntu >= 20.04 - snap install jq ansible
  4. Arch - pacman -S jq ansible

Script usage example

Shown here is an application of the example terraform scripts in examples/3.k8s of my Proxmox module that uses the Telmate Proxmox provider. Refer to that example.

After running your terraform apply , it will create the terraform.tfstate file:

$ ls -l
total 40
-rw-r--r-- 1 brian brian  1217 Dec 14 03:34 main.tf
-rw-r--r-- 1 brian brian 18378 Dec 14 03:31 terraform.tfstate
-rw-r--r-- 1 brian brian  5655 Dec 14 03:30 terraform.tfstate.backup

You then run this script telmate_proxmox_tf_ansible.sh in the same directory as your terraform.tfstate file. It will create the inventory file hosts.txt suitable for use with Ansible. It can also optionally download the public SSH host keys from each new VM and put the public host keys into the user's $HOME/.ssh/known_hosts file. This is needed for SSH to work with Ansible.

$ telmate_proxmox_tf_ansible.sh
Created Ansible inventory file 'hosts.txt'

Do you want to import the public SSH host keys
for all hosts in the inventory?

  Yes or No? (default: Yes) >>> yes

Done!

Looking at the file hosts.txt you will see that it is compatible with the k3s installer, making it very easy to simply run the official k3s playbook with this hosts.txt file:

$ cat hosts.txt

# This hosts file is compatible with the official k3s playbook at
# https://github.com/k3s-io/k3s-ansible

[all:children]
master
node

[k3s_cluster:children]
master
node

[master]
192.168.0.75    # k8s-server-1

[node]
192.168.0.88    # k8s-worker-1
192.168.0.99    # k8s-worker-2
192.168.0.92    # k8s-worker-3

Now try to ping each host using this hosts.txt file and the Ansible ping module:

 $ ansible -i hosts.txt all -u ubuntu -m ping -v
Using /home/brian/.ansible.cfg as config file
192.168.0.75 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.0.88 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.0.99 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.0.92 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
#!/bin/bash
#
# This script is helpful for creating an Ansible inventory file of
# hosts created using the telmate/proxmox terraform provider.
#
# It will read the terraform.tfstate after creating hosts and extract the
# master and worker node IP addresses and create the ansible inventory file
#
# It will also optionally run commands to remove old IPs from the user's
# ~/.ssh/known_hosts file and then insert the new public host keys for each
# host. This will eliminate the SSH warning about possible attacks
# (because the hosts public key has changed)
#
# default output file
INVENTORY="hosts.ini"
STATE="terraform.tfstate"
[ ! -r "$STATE" ] && echo "Run this in the same directory where your $STATE file is kept." && exit 1
# gather the server node(s)
servers=$(cat terraform.tfstate | \
jq -r '
.resources[]
| select(.provider|match("telmate"))
| .instances[].attributes
| select(.name|match("server"))
| ( .ssh_host + "\t# " + .name )
')
# gather the worker node(s)
workers=$(cat terraform.tfstate | \
jq -r '
.resources[]
| select(.provider|match("telmate"))
| .instances[].attributes
| select(.name|match("worker"))
| ( .ssh_host + "\t# " + .name )
')
rm -f ${INVENTORY}
cat > ${INVENTORY} <<!
# This hosts file is compatible with the official k3s playbook at
# https://github.com/k3s-io/k3s-ansible
[all:children]
master
node
[k3s_cluster:children]
master
node
[master]
${servers}
[node]
${workers}
!
echo "Created Ansible inventory file '${INVENTORY}'"
echo
echo "Do you want to import the public SSH host keys"
echo "for all hosts in the inventory?"
echo
echo -n " Yes or No? (default: Yes) >>> "
read ans
echo
case $ans in
n|N|no|NO|No)
echo "Not updating ${HOME}/.ssh/known_hosts"
echo "You might experience SSH errors when running Ansible"
exit 0
;;
*)
allips=$(echo -ne "${servers} \n ${workers}" | awk '/^[0-9]*/ {print $1}')
for ip in ${allips}; do
ssh-keygen -R $ip >/dev/null 2>&1
done
ssh-keyscan ${allips} 2>/dev/null >> ${HOME}/.ssh/known_hosts
chmod 0600 ${HOME}/.ssh/known_hosts
echo "Done!"
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment