diff --git a/cloud_init.cfg b/cloud_init.cfg index 4b4f11c..5266096 100644 --- a/cloud_init.cfg +++ b/cloud_init.cfg @@ -26,15 +26,17 @@ chpasswd: hostname: ${hostname} fqdn: ${hostname} +%{ if install-qemu-agent } packages: - # TODO These are only necessary for libvirt. + # This are only necessary for libvirt. - qemu-guest-agent runcmd: # TODO At some point revisit this, this was added because it seemed like # apparmor was causing dhclient to not get an IP address for ubuntu. This # should be double checked. - echo "/proc/*/task/*/comm wr," | tee -a /etc/apparmor.d/local/sbin.dhclient - # TODO These are only necessary for libvirt. + # These are only necessary for libvirt. - systemctl enable qemu-guest-agent - systemctl start qemu-guest-agent - systemctl status qemu-guest-agent +%{ endif } diff --git a/example.tfvars b/example.tfvars index 5754315..2131e2e 100644 --- a/example.tfvars +++ b/example.tfvars @@ -68,6 +68,11 @@ base-image = "ami-0dd0ccab7e2801812" # on 2021-11-28 # base-image = "/media/nas/software/isos/Arch-Linux-x86_64-libvirt-20211128.40102.box" +## Arch +# From https://gitlab.archlinux.org/archlinux/arch-boxes/-/jobs/40102/artifacts/browse/output +# on 2021-11-28 +# base-image = "/media/nas/software/isos/Arch-Linux-x86_64-libvirt-20211128.40102.box" + ################################################################################ # Keys/Passwords ################################################################################ diff --git a/get-vm-ips.sh b/get-vm-ips.sh index 230b5cf..b8ab1df 100755 --- a/get-vm-ips.sh +++ b/get-vm-ips.sh @@ -1,60 +1,92 @@ -#!/bin/sh +#!/bin/bash -# This script will create environment variables for all of the output IPs. It -# will also create a `ANSIBLE_INV` variable that will be a comma separated -# string of all the IPs. A anisble inventory file called "inventory is created -# as well. +# This script will create environment variables for all of the output IPs. An +# anisble inventory file is created as well. # # Use eval $(./get-vm-ips.sh) to set env vars for ips. terraform refresh > /dev/null -# All terraform outputs in json format. -OUTPUTS_JSON="$( - terraform show -json | \ - jq '.values.outputs' | \ - sed 's/-/_/g')" -# Just the IP address outputs in json format. Also all '-' characters are -# replaced by '_' becuase '-' causes jq some problems. -IPS_JSON="$( - echo $OUTPUTS_JSON | \ - jq 'to_entries | .[] | select(.key | contains("ips"))')" -# An array of all node "types" -NODE_TYPE_ARRAY="$( - echo $IPS_JSON | \ - jq '.value.value | to_entries | .[] | .key' | \ - sed 's/"//g' | \ - sed -z 's/\n/ /g;s/ $/\n/g')" - -# Loop over all the node types and create an export line for each IP. -VM_IP_EXPORTS="$( - for TYPE in $NODE_TYPE_ARRAY; do - - # Convert type, converts "master-ips" to "MASTER" - TYPE_UPPER="$(echo ${TYPE^^} | sed s/_.*$//g)" - echo "$IPS_JSON" | \ - jq '.value.value.'"$TYPE"'[]' | \ - # Add line numbers starting with 0. - nl -v 0 | \ - # Print an export string with a type placeholder "__TYPE__". - awk '{print "export __TYPE___" $1 "=" $2}' | \ - sed s/__TYPE__/$TYPE_UPPER/g - done)" - -ANSIBLE_INV="$( - echo "$VM_IP_EXPORTS" | \ +# The file to write the inventory to. This file will be completely overridden. +INVENTORY_FILE="inventory" + +# Grab the the vm name prefix. We do this by greping all *.tfvars files making +# sure to cat terraform.tfvars last. Then we just grab the last grep result, +# this way we make sure any value in terraform.tfvars will take priority. +VM_NAME_PREFIX_VAR="vm-name-prefix" +VM_NAME_PREFIXES="$( \ + find . -name "*.tfvars" -exec grep "$VM_NAME_PREFIX_VAR" {} \; && \ + grep "$VM_NAME_PREFIX_VAR" terraform.tfvars)" +VM_NAME_PREFIX="$( + echo "$VM_NAME_PREFIXES" | \ + tail -n 1 | \ + sed 's/^.*=\s*"\(.*\)"/\1/g')" + +# This command stores the output data in the format below. +# [ +# { +# "group": "master", +# "vms": [ +# { +# "hostname": "ansible-test-master-0", +# "ip": "52.14.114.48" +# } +# ] +# }, +# { +# "group": "worker", +# "vms": [ +# { +# "hostname": "ansible-test-worker-0", +# "ip": "3.145.121.159" +# }, +# { +# "hostname": "ansible-test-worker-1", +# "ip": "18.217.112.176" +# } +# ] +# } +# ] +DATA="$(terraform show -json | \ + jq '.values.outputs.groups_hostnames_ips.value | to_entries | + map({group: .key, vms:.value | to_entries | + map({hostname:.key,ip:.value})})')" + +# Pull out the groups from $DATA. The format is a single string with the groups +# separated by spaces, ie. "group1 group2 group3". +ANS_GROUPS="$( + echo $DATA | \ + jq '.[] | .group' | \ sed 's/"//g' | \ - sed 's/^.*=//g' | \ - sed -z 's/\n/,/g;s/,$/\n/g')" - -# Create an inventory file for ansible. -echo "[k8s_nodes]" > inventory -echo $VM_IP_EXPORTS | \ - sed 's/"//g' | \ - sed 's/export //g' | \ - sed 's/ /\n/g' | \ - sed 's/^\(.*\)\(=.*\)$/\1 ansible_host\2/g' \ - >> inventory - -echo $VM_IP_EXPORTS | sed 's/" /"\n/g' -echo export ANSIBLE_INV=$ANSIBLE_INV + tr '\n' ' ' + )" + +# Clear the inventory file. +cat /dev/null > $INVENTORY_FILE + +# For each group, write the VM info to $INVENTORY_FILE and also print a variable +# expression to stdout. +for GROUP in $ANS_GROUPS; do + + # Write the inventory file to $INVENTORY_FILE. + echo "[$GROUP]" >> $INVENTORY_FILE + echo $DATA | \ + jq '.[] | select(.group=="'"$GROUP"'") | .vms[] | + "\(.hostname) ansible_host=\(.ip)"' | \ + sed 's/"//g' \ + >> $INVENTORY_FILE + + # For this group, collect expressions into VARS. The format is: + # HOSTNAME1=0.0.0.0 + # HOSTNAME2=0.0.0.0 + VARS="$( + echo $DATA | \ + jq '.[] | select(.group=="'"$GROUP"'") | .vms[] | + "\(.hostname)=\(.ip)"' | \ + sed 's/"//g' | \ + sed "s/$VM_NAME_PREFIX-//g" | \ + sed 's/-/_/g' + )" + # Print the contents of $VARS converted to uppercase. + echo "${VARS^^}" +done diff --git a/main.tf b/main.tf index 36222c5..c20f4e6 100644 --- a/main.tf +++ b/main.tf @@ -10,35 +10,16 @@ terraform { locals { nodes-config = { - "amzn2" = { - base-image = var.amzn2-ami - num = 1 - }, - "ubuntu" = { - base-image = var.ubuntu-ami - num = 1 - }, - "arch" = { - base-image = var.arch-ami - num = 1 - }, - "centos7" = { - base-image = var.centos7-ami - num = 1 - }, - "centos8" = { + "master" = { base-image = var.centos8-ami num = 1 }, - "rhel7" = { - base-image = var.rhel7-ami - num = 1 - }, - "rhel8" = { - base-image = var.rhel8-ami - num = 1 + "worker" = { + base-image = var.centos8-ami + num = 2 } } + install-qemu-agent = false } ################################################################################ @@ -53,6 +34,7 @@ module "cloud-init-config" { num = each.value.num root-admin-passwd = var.root-admin-passwd root-admin-pub-key = var.root-admin-pub-key + install-qemu-agent = local.install-qemu-agent } ################################################################################ @@ -145,6 +127,8 @@ module "nodes" { # end libvirt ################################################################################ -output "ips" { - value = { for type, node in module.nodes : type => node.ips } +# This will outpus a map of group => [{hostname, ip}]. +# TODO A 'names' output needs to be added to libvirt. +output "groups_hostnames_ips" { + value = { for type, node in module.nodes : type => zipmap(node.names, node.ips) } } diff --git a/modules/aws-network/main.tf b/modules/aws-network/main.tf index be001ac..6056fc0 100644 --- a/modules/aws-network/main.tf +++ b/modules/aws-network/main.tf @@ -33,7 +33,7 @@ resource "aws_default_security_group" "sg" { } tags = { - Name = "${var.name-prefix}-ssh-from-admins--sg" + Name = "${var.name-prefix}-ssh-from-admins-sg" } } diff --git a/modules/aws-nodes/outputs.tf b/modules/aws-nodes/outputs.tf index d6faaf0..0b4fe7c 100644 --- a/modules/aws-nodes/outputs.tf +++ b/modules/aws-nodes/outputs.tf @@ -1,3 +1,7 @@ output "ips" { value = aws_instance.nodes.*.public_ip } + +output "names" { + value = aws_instance.nodes.*.tags.Name +} diff --git a/modules/cloud-init-config/main.tf b/modules/cloud-init-config/main.tf index e1c75c4..6b5beed 100644 --- a/modules/cloud-init-config/main.tf +++ b/modules/cloud-init-config/main.tf @@ -1,9 +1,10 @@ data "template_file" "user-datas" { template = file("${var.cloud-init-template}") vars = { - admin-passwd = "${var.root-admin-passwd}" - admin-pub-key = "${var.root-admin-pub-key}" - hostname = "${var.hostname-prefix}-${count.index}" + admin-passwd = "${var.root-admin-passwd}" + admin-pub-key = "${var.root-admin-pub-key}" + hostname = "${var.hostname-prefix}-${count.index}" + install-qemu-agent = var.install-qemu-agent } count = var.num } diff --git a/modules/cloud-init-config/variables.tf b/modules/cloud-init-config/variables.tf index fc4f437..a1b0f2d 100644 --- a/modules/cloud-init-config/variables.tf +++ b/modules/cloud-init-config/variables.tf @@ -8,6 +8,12 @@ variable "hostname-prefix" { description = "This prefix wil be applied as a prefix for the hostnames." } +variable "install-qemu-agent" { + default = false + description = "This flag determines whether or not qemu-agent is installed." + type = bool +} + variable "num" { description = "The number of user-datas to create with these parameters." }