HashiQube - DevOps Lab
Youtube Channel Medium Posts Riaan Nolan Linkedin Riaan Nolan Hashicorp Ambassador

.

Ansible AWX Tower

Ansible AWX Tower Logo

Centralize and control your IT infrastructure with a powerful web-based automation platform

🚀 About

In this HashiQube DevOps Lab, you'll get hands-on experience with Ansible AWX Tower - a web-based user interface, REST API, and task engine built on top of Ansible. AWX Tower provides a robust platform for:

  • Managing credentials, inventories, projects, and playbooks
  • Configuring AWX Tower using the CLI
  • Triggering Ansible runs programmatically

AWX is the upstream open-source project for Red Hat Ansible Automation Platform, giving you enterprise-grade automation capabilities including:

  • Visual dashboard for infrastructure management
  • Role-based access control
  • Job scheduling
  • Integrated notifications
  • Graphical inventory management
  • REST API and CLI for integration with existing tools and processes

📋 Quick Start

Open in GitHub Codespaces

bash docker/docker.sh
bash minikube/minikube.sh
bash ansible-tower/ansible-tower.sh
vagrant up --provision-with basetools,docker,docsify,minikube,ansible-tower
docker compose exec hashiqube /bin/bash
bash bashiqube/basetools.sh
bash docker/docker.sh
bash docsify/docsify.sh
bash minikube/minikube.sh
bash ansible-tower/ansible-tower.sh

🔍 Access Information

After provisioning, you can access AWX Ansible Tower at:

Ansible Tower Dashboard

AWX Ansible Tower Dashboard

Ansible Tower Password

The login password is displayed at the end of the provisioning process

🛠️ Working with AWX Tower

The following components were automatically configured during provisioning, but this guide will show you how to create them manually as well.

Adding a Project

Projects in AWX Tower represent a collection of Ansible playbooks. You can connect to source control management (SCM) systems like Git.

Add Project

Creating a new project in AWX Tower

# Command used during auto-provisioning:
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx projects create \
  --organization 'Default' \
  --scm_update_on_launch true \
  --scm_url https://github.com/star3am/ansible-role-example-role \
  --scm_type git \
  --name ansible-role-example-role \
  --description ansible-role-example-role \
  --wait $AWX_COMMON

Adding Credentials

Credentials allow AWX Tower to authenticate with the systems you're managing.

Add Credential

Creating machine credentials in AWX Tower

# Command used during auto-provisioning:
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx credentials create \
  --credential_type 'Machine' \
  --organization 'Default' \
  --name 'ansible' \
  --inputs '{"username": "vagrant", "password": "vagrant"}' \
  $AWX_COMMON

Creating an Inventory

Inventories define the hosts and groups that AWX Tower will manage.

Add Inventory

Creating a new inventory in AWX Tower

# Command used during auto-provisioning:
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx inventory create \
  --name 'Demo Inventory' \
  --description 'Demo Inventory' \
  --organization 'Default' \
  --wait $AWX_COMMON

Setting Up a Job Template

Job templates combine projects, inventories, and credentials to create runnable automation tasks.

Add Job Template

Creating a job template in AWX Tower

Additional Template Settings

Additional job template settings for triggering capabilities

# Command used during auto-provisioning:
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates create \
  --name ansible-role-example-role \
  --description ansible-role-example-role \
  --job_type run \
  --inventory 'Demo Inventory' \
  --project 'ansible-role-example-role' \
  --become_enabled true \
  --ask_limit_on_launch true \
  --ask_tags_on_launch true \
  --playbook site.yml \
  --ask_variables_on_launch true \
  --wait $AWX_COMMON

▶️ Triggering Jobs

Using the Callback URL

One powerful feature of AWX Tower is the ability to trigger jobs via API callbacks:

# SSH into Hashiqube
vagrant ssh

# Trigger an Ansible run via API callback
curl -s -i -X POST -H Content-Type:application/json \
  --data '{"host_config_key": "UL3H6uRtDozHA13trZudrUwUPBw4rSo7rRvi"}' \
  https://10.9.99.10:8043/api/v2/job_templates/9/callback/ -v -k
Jobs View

Jobs view showing successful job execution

Job Details

Detailed job execution information

Working with Windows Hosts

When working with Windows hosts, additional configuration is required:

Windows Job Template

Creating a job template for Windows hosts

Windows Template Extra Vars

Extra variables needed for Windows automation

# Required extra variables for Windows hosts
ansible_shell_type: cmd
ansible_connection: ssh

To trigger a Windows job via PowerShell:

powershell.exe -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true };Invoke-WebRequest -UseBasicParsing -Uri https://10.9.99.10:8043/api/v2/job_templates/10/callback/ -Method POST -Body @{host_config_key='UL3H6uRtDozHA13trZudrUwUPBw4rSo7rRvi'}"
Windows Job Details

Windows job execution details

🧰 Using AWX CLI

AWX CLI provides a powerful way to interact with AWX Tower from the command line, making it ideal for integration with CI/CD pipelines:

# Install the CLI tools
pip3 install awxkit         # For AWX
pip3 install ansible-tower-cli  # For Ansible Tower

# Example: Launch a job template and monitor its status
awx --conf.host https://10.9.99.10:8043 -f human job_templates launch 9 \
  --monitor --filter status --conf.insecure \
  --conf.username admin --conf.password password

🔄 Integration with Terraform

You can easily integrate AWX Tower with Terraform for infrastructure automation:

locals {
  timestamp = timestamp()
}

resource "null_resource" "awx_cli" {
  triggers = {
    timestamp = local.timestamp
  }

  provisioner "remote-exec" {
    inline = [
      "/home/vagrant/.local/bin/awx --conf.host https://10.9.99.10:8043 -f human job_templates launch 9 --monitor --filter status --conf.insecure --conf.username admin --conf.password password",
    ]

    connection {
      type     = "ssh"
      user     = "vagrant"
      password = "vagrant"
      host     = "10.9.99.10"
    }
  }

  provisioner "local-exec" {
    command = "/usr/local/bin/awx --conf.host https://10.9.99.10:8043 -f human job_templates launch 9 --monitor --filter status --conf.insecure --conf.username admin --conf.password password"
  }
}

📚 Additional Resources

#!/bin/bash

# https://github.com/ansible/awx-operator#basic-install
# https://docs.ansible.com/ansible-tower/latest/html/towercli/index.html
# https://github.com/ansible/awx/blob/17.0.1/INSTALL.md
# https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md
# https://github.com/ansible/awx
# https://blog.palark.com/ready-to-use-commands-and-tips-for-kubectl/
# https://techfrontier.me.uk/post/finally-my-own-awx-server/

# DEBUG: kubectl -n awx logs -f deployment/awx-demo -c awx-demo-web
# https://github.com/kurokobo/awx-on-k3s/blob/main/tips/troubleshooting.md#investigate-logs-of-the-containers-inside-the-podsgit

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Add ~/.local/bin to PATH"
echo -e '\e[38;5;198m'"++++ "
export PATH="/home/vagrant/.local/bin:$PATH"
sudo --preserve-env=PATH -u vagrant env | grep PATH

# https://github.com/ansible/awx/blob/17.0.1/INSTALL.md#clone-the-repo
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Clone https://github.com/ansible/awx.git into /opt/awx"
echo -e '\e[38;5;198m'"++++ "
sudo rm -rf /opt/awx
sudo mkdir -p /opt/awx
sudo chown -R vagrant:vagrant /opt/awx
sudo --preserve-env=PATH -u vagrant git clone https://github.com/ansible/awx.git /opt/awx --depth 1 --branch 22.5.0 # 21.7.0 # 24.6.1

cd /opt/awx

# https://github.com/ansible/awx/blob/17.0.1/INSTALL.md#prerequisites
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Install Ansible and AWX dependencies with pip"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant python -m pip install docker --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install docker-compose --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install ansible --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install ansible-lint --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install wheel --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install pywinrm --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install requests --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install docker --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install molecule --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install junit_xml --break-system-packages --quiet
sudo --preserve-env=PATH -u vagrant python -m pip install awxkit --break-system-packages --quiet

# BUG: https://techfrontier.me.uk/post/finally-my-own-awx-server/
# Back-off pulling image "quay.io/ansible/awx-ee:latest"
# This looks to relate image "quay.io/ansible/awx-ee:latest" being large and not pulling quick enough, so we manually intervene and get it into our docker library by hand.
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Pull quay.io/ansible/awx-ee:latest to avoid Back-off pulling image later"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant minikube ssh docker pull quay.io/ansible/awx-ee:latest

# 
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create kustomization.yaml"
echo -e '\e[38;5;198m'"++++ "
cat <<EOF | sudo --preserve-env=PATH -u vagrant tee ./kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  # Find the latest tag here: https://github.com/ansible/awx-operator/releases
  - github.com/ansible/awx-operator/config/default?ref=1.1.4 # 2.19.1

# Set the image tags to match the git version from above
images:
  - name: quay.io/ansible/awx-operator
    newTag: 1.1.4 # 2.19.1

# Specify a custom namespace in which to install AWX
namespace: awx
EOF

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create awx.yaml with kubectl kustomize > awx.yaml"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant kubectl kustomize > awx.yaml
cat awx.yaml

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create AWX resources using kubectl apply -f awx.yaml"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant kubectl apply -f awx.yaml

# https://github.com/ansible/awx/blob/17.0.1/INSTALL.md#post-install-1
attempts=0
max_attempts=20
while ! ( sudo --preserve-env=PATH -u vagrant kubectl get pods --namespace awx | grep controller | tr -s " " | cut -d " " -f3 | grep Running ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ Waiting for AWX Controller to become available, (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl get po --namespace awx
  sudo --preserve-env=PATH -u vagrant kubectl get events | grep -e Memory -e OOM
done

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create awx-demo.yaml and add to kustomization.yaml"
echo -e '\e[38;5;198m'"++++ "
cat <<EOF | sudo --preserve-env=PATH -u vagrant tee ./awx-demo.yaml
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
  name: awx-demo
spec:
  ee_images:
    - name: quay.io/ansible/awx-ee:latest
      image: quay.io/ansible/awx-ee:latest
  service_type: nodeport
  # default nodeport_port is 30080
  nodeport_port: 30080
EOF

if [[ $CODESPACES == true ]]; then
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Adding Github Codespace Name in CSRF_TRUSTED_ORIGINS awx-demo.yaml"
echo -e '\e[38;5;198m'"++++ "
cat <<EOF | sudo --preserve-env=PATH -u vagrant tee -a ./awx-demo.yaml
  extra_settings:
  - setting: CSRF_TRUSTED_ORIGINS
    value:
      - https://$CODESPACE_NAME-8043.app.github.dev
      - $CODESPACE_NAME-8043.app.github.dev
  - setting: SECURE_PROXY_SSL_HEADER
    value:
      - HTTP_X_FORWARDED_PROTO
      - https
EOF
fi

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ DEBUG: cat awx-demo.yaml"
echo -e '\e[38;5;198m'"++++ "
cat ./awx-demo.yaml

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Add awx-demo.yaml to kustomization.yaml"
echo -e '\e[38;5;198m'"++++ "
cat <<EOF | sudo --preserve-env=PATH -u vagrant tee ./kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  # Find the latest tag here: https://github.com/ansible/awx-operator/releases
  - github.com/ansible/awx-operator/config/default?ref=1.1.4 # 2.19.1
  - awx-demo.yaml

# Set the image tags to match the git version from above
images:
  - name: quay.io/ansible/awx-operator
    newTag: 1.1.4 # 2.19.1

# Specify a custom namespace in which to install AWX
namespace: awx
EOF

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create awx.yaml with kubectl kustomize > awx.yaml"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant kubectl kustomize > awx.yaml

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create AWX resources using kubectl apply -f awx.yaml"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant kubectl apply -f awx.yaml

attempts=0
max_attempts=30
while ! ( sudo --preserve-env=PATH -u vagrant kubectl get pods --namespace awx | grep demo | grep -v postgres | tr -s " " | cut -d " " -f3 | grep Running ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ Waiting for AWX Demo to become available, (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl get po --namespace awx
  sudo --preserve-env=PATH -u vagrant kubectl get events | grep -e Memory -e OOM
done
sleep 30;

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Get the AWX password"
echo -e '\e[38;5;198m'"++++ "
AWX_ADMIN_PASSWORD=$(sudo --preserve-env=PATH -u vagrant kubectl get secret awx-demo-admin-password -n awx -o jsonpath="{.data.password}" | base64 --decode)
echo "AWX Admin Password: $AWX_ADMIN_PASSWORD"

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Check that AWX Ansible Tower web interface is available"
echo -e '\e[38;5;198m'"++++ "
attempts=0
max_attempts=30
while ! ( sudo --preserve-env=PATH -u vagrant kubectl exec $(sudo --preserve-env=PATH -u vagrant kubectl get po -n awx | grep -v operator | grep -v postgres | grep awx | tr -s " " | cut -d " " -f1) --container="redis" -n awx -- /bin/bash -c "apt-get -qqq update && apt-get -qqq install -y procps curl net-tools && netstat -nlp | grep 8052" ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ Waiting for AWX Ansible Tower web interface to become ready, (${attempts}/${max_attempts}) sleep 60s"
  sudo --preserve-env=PATH -u vagrant kubectl exec $(sudo --preserve-env=PATH -u vagrant kubectl get po -n awx | grep -v operator | grep -v postgres | grep awx | tr -s " " | cut -d " " -f1) --container="redis" -n awx -- /bin/bash -c "ps aux; netstat -nlp"
done

attempts=0
max_attempts=20
while ! ( sudo netstat -nlp | grep 8043 ) && (( $attempts < $max_attempts )); do
  attempts=$((attempts+1))
  sleep 60;
  echo -e '\e[38;5;198m'"++++ "
  echo -e '\e[38;5;198m'"++++ kubectl port-forward -n awx service/awx-demo-service 8043:80 --address=\"0.0.0.0\", (${attempts}/${max_attempts}) sleep 60s"
  echo -e '\e[38;5;198m'"++++ "
  sudo --preserve-env=PATH -u vagrant kubectl port-forward -n awx service/awx-demo-service 8043:80 --address="0.0.0.0" > /dev/null 2>&1 &
done

# https://docs.ansible.com/ansible-tower/latest/html/towercli/index.html
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Export AWX_COMMON variables"
echo -e '\e[38;5;198m'"++++ "
export AWX_COMMON="--conf.format human --conf.insecure --conf.host http://localhost:8043 --conf.username admin --conf.password $AWX_ADMIN_PASSWORD"

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Adding /home/vagrant/.tower_cli.cfg and doing awx-cli login"
echo -e '\e[38;5;198m'"++++ "
cat <<EOF | sudo --preserve-env=PATH -u vagrant tee /home/vagrant/.tower_cli.cfg
[general]
verify_ssl = False
insecure = True
description_on = False
host = http://localhost:8043
color = True
oauth_token =
certificate =
use_token = False
format = human
username = admin
verbose = True
password = $AWX_ADMIN_PASSWORD
EOF

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-organizations-list
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Check if Default organisation exists"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx organizations list --wait $AWX_COMMON | grep -q "Default"
if [ $? -eq 1 ]; then
  echo -e '\e[38;5;198m'"++++ Organization 'Default' doesn't exist, creating"
  sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx organizations create --name "Default" --description "Default" --wait $AWX_COMMON
else
  echo -e '\e[38;5;198m'"++++ Organization 'Default' exists"
fi

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-inventory-list
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Check if 'Demo Inventory' exists"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx inventory list --wait $AWX_COMMON | grep -q 'Demo Inventory'
if [ $? -eq 1 ]; then
  echo -e '\e[38;5;198m'"++++ 'Demo Inventory' doesn't exist, creating"
  sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx inventory create --name 'Demo Inventory' --description 'Demo Inventory' --organization 'Default' --wait $AWX_COMMON
else
  echo -e '\e[38;5;198m'"++++ 'Demo Inventory' exists"
fi

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-projects-create
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create projects ansible-role-example-role"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx projects create --organization 'Default' --scm_update_on_launch true --scm_url https://github.com/star3am/ansible-role-example-role --scm_type git --name ansible-role-example-role --description ansible-role-example-role --wait $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-job-templates-create
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Create job_templates ansible-role-example-role"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates create --name ansible-role-example-role --description ansible-role-example-role --job_type run --inventory 'Demo Inventory' --project 'ansible-role-example-role' --become_enabled true --ask_limit_on_launch true --ask_tags_on_launch true --playbook site.yml --ask_limit_on_launch true --ask_tags_on_launch true --ask_variables_on_launch true --wait $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-credentials-create
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Add credentials ansible"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx credentials create --credential_type 'Machine' --organization 'Default' --name 'ansible' --inputs '{"username": "vagrant", "password": "vagrant"}' $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-job-templates
# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ Associate credential with job_templates Demo Job Template"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates disassociate --credential "Demo Credential" --name "Demo Job Template" --wait $AWX_COMMON || true
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates associate --credential "ansible" --name "Demo Job Template" --wait $AWX_COMMON || true

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-job-templates
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Associate credential with job_templates ansible-role-example-role"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates associate --credential "ansible" --name "ansible-role-example-role" $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-projects-update
# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ Update the project"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx projects update "Demo Project" --wait $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-projects-modify
# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ Disable project update"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx projects modify 'Demo Project' --scm_update_on_launch false --wait $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-workflow-job-templates-modify
# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ Modify job_templates Demo Job Template"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates modify "Demo Job Template" --name "Demo Job Template" --ask_limit_on_launch true --ask_tags_on_launch true $AWX_COMMON

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Configure SSH to allow login with password"
echo -e '\e[38;5;198m'"++++ "
sudo sed -i "s/PasswordAuthentication no/PasswordAuthentication yes/g" /etc/ssh/sshd_config
sudo systemctl restart ssh

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-hosts-create
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Add VM host to Ansible Tower inventory"
echo -e '\e[38;5;198m'"++++ "
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx hosts create --id 172.18.0.1 --description $(hostname) --inventory 1 --enabled true --name 172.18.0.1 $AWX_COMMON

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-job-templates-launch
echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ Run Ansible Tower job_template"
echo -e '\e[38;5;198m'"++++ sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates launch ansible-role-example-role \
  --limit 172.18.0.1 \
  --monitor \
  --filter status $AWX_COMMON \
  --extra_vars \"{\"vm_name\":\"$(hostname)\", \"vm_ip\":\"172.18.0.1\"}\""
echo -e '\e[38;5;198m'"++++ "
# Specify job tags to target specific role task e.g --job_tags "day0,day1,always"
sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx job_templates launch ansible-role-example-role \
  --limit 172.18.0.1 \
  --monitor \
  --filter status $AWX_COMMON \
  --extra_vars "{\"vm_name\":\"$(hostname)\", \"vm_ip\":\"172.18.0.1\"}"

# https://docs.ansible.com/ansible-tower/latest/html/towercli/reference.html#awx-hosts-delete
# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ Remove VM host from Ansible Tower inventory"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx hosts delete --id "$(sudo --preserve-env=PATH -u vagrant /home/vagrant/.local/bin/awx hosts list $AWX_COMMON | grep "172.18.0.1" | cut -d ' ' -f1)" $AWX_COMMON

# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ DEBUG with kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager -n awx"
# echo -e '\e[38;5;198m'"++++ "
# sudo --preserve-env=PATH -u vagrant kubectl logs -f deployments/awx-operator-controller-manager -c awx-manager -n awx

# echo -e '\e[38;5;198m'"++++ "
# echo -e '\e[38;5;198m'"++++ DEBUG CSRF Login issues"
# echo -e '\e[38;5;198m'"++++ "
# https://ansible.readthedocs.io/projects/awx-operator/en/latest/user-guide/advanced-configuration/csrf-cookie-secure-setting.html
# https://github.com/ansible/awx-operator#extra-settings
# https://github.com/ansible/awx/issues/14024#issuecomment-1557919352
# sudo --preserve-env=PATH -u vagrant kubectl exec -it awx-demo-5d9dc64cc7-kbhws -c awx-demo-web -n awx -- grep CSRF_TRUSTED_ORIGINS /etc/tower/settings.py
# sudo --preserve-env=PATH -u vagrant kubectl logs -f awx-demo-5d9dc64cc7-kbhws -c awx-demo-web -n awx

echo -e '\e[38;5;198m'"++++ "
echo -e '\e[38;5;198m'"++++ You can now access the AWX Ansible Web Interface at http://localhost:8043"
echo -e '\e[38;5;198m'"++++ Login with Username: admin and Password: $AWX_ADMIN_PASSWORD"
echo -e '\e[38;5;198m'"++++ Documentation can be found at http://localhost:3333/#/ansible-tower/README"
echo -e '\e[38;5;198m'"++++ DEBUG: kubectl -n awx logs -f deployment/awx-demo -c awx-demo-web"
echo -e '\e[38;5;198m'"++++ "
variable "tower_cli_remote" {
  type    = string
  default = "~/.local/bin/awx"
}

variable "tower_cli_local" {
  type    = string
  default = "/home/vagrant/.local/bin/awx"
}

variable "tower_host" {
  type    = string
  default = "http://localhost:8043/"
}

variable "tower_password" {
  type      = string
  sensitive = true
  default   = "password"
}

data "external" "tower_token" {
  program = ["/bin/bash", "-c", "${var.tower_cli_local} login --conf.host ${var.tower_host} --conf.insecure --conf.username admin --conf.password \"${var.tower_password}\""]
}

locals {
  timestamp = timestamp()
}

resource "null_resource" "awx_cli" {
  triggers = {
    timestamp = local.timestamp
  }

  provisioner "remote-exec" {
    inline = [
      "${var.tower_cli_remote} --conf.host ${var.tower_host} -f human job_templates launch ansible-role-example-role --monitor --filter status --conf.insecure --conf.token ${data.external.tower_token.result.token}",
    ]
    on_failure = continue
    connection {
      type        = "ssh"
      user        = "vagrant"
      password    = "vagrant"
      host        = "localhost"
    }
  }
  
  provisioner "local-exec" {
    command    = "${var.tower_cli_local} --conf.host ${var.tower_host} -f human job_templates launch ansible-role-example-role --monitor --filter status --conf.insecure --conf.token ${data.external.tower_token.result.token}"
    on_failure = continue
  }
}