I've managed to automate kubernetes cluster deployment with terraform. After bringing up cluster terraform also deploys my apps to cluster using provisioning (running .sh script with local-exec). I am also adding ingress to cluster and I need to get the ingress load balancer IP once it created. preferable option is terraform output. The way I am getting it now is running this part of code at the end of my script
IP="$(kubectl get ingress appname --no-headers | awk '{print $3}')"
echo "Load Balancer IP $IP"
However this one has its issues, I need to add sleep before running this command to be sure that the IP is already assigned. and I can't be sure the added sleep time is enough. Actually need smth like these but for my ingress loadbalancer IP
output "google_container_cluster_endpoint" {
value = "${google_container_cluster.k8s.endpoint}"
}
output "google_container_cluster_master_version" {
value = "${google_container_cluster.k8s.master_version}"
}
After a long Saturday, I've end up with a solution to the the problem. I was with almost the same issue, so here is my solution, surely can be improved.
I divided in two parts:
1.- I'll use local-exec to run a script that solves the problem of waiting for a valid IP in the load LoadBalancer 2.-Terraform, using External Data Source calls a "program" that answers in json format. My "program" is a bash script that grabs the IP. As a result, I have my desired data in a variable.
I did it this way cause I didn't know how to debug issues using External Data Source and I was suffering "Stranger things"
First I run the code to wait for a valid IP. Terraform calls the local-exec
provisioner "local-exec" {
command = "./public-ip.sh"
interpreter = ["/bin/bash", "-c"]
}
And this is the script I've used
#!/bin/bash
#public-ip.sh
#!/bin/bash
# Exit if any of the intermediate steps fail
set -e
function valid_ip()
{
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}
########################
# Grab the Public IP #
#######################
WaitingTime=0
HaveIP=NO
echo "Let's check that LoadBalancer IP..."
MyPublicIP=$(kubectl get services --all-namespaces| grep LoadBalancer | awk '{print $5}')
valid_ip $MyPublicIP && HaveIP="OK"
until [ "$HaveIP" = "OK" -o "$WaitingTime" -ge 30 ]; do
echo "sleeeping...."
sleep 10
echo "Play it again Sam..."
MyPublicIP=$(kubectl get services --all-namespaces| grep LoadBalancer | awk '{print $5}')
#if valid_ip $MyPublicIP; then echo "We got the IP"; HaveIP=YES ;else stat='Still without IP'; fi
#if valid_ip $MyPublicIP; then HaveIP="OK" ; fi
valid_ip $MyPublicIP && HaveIP="OK"
#if valid_ip $MyPublicIP; then HaveIP="OK" ; fi
WaitingTime=$((WaitingTime+1))
echo $WaitingTime
done
if [ "$HaveIP" = "OK" ]; then echo An the public IP is... $MyPublicIP; else echo "WT_ has happened now!!!"; fi
After I know I have the IP ready. I've just needed to grab it. Pay attention to the depends_on that controls I'll grab my data once my resource (google_container_cluster.tests) it's been created, and not whenever he wants. Test it. It's tricky...
data "external" "insights-public-ip" {
program = ["sh", "test-jq.sh" ]
depends_on = ["google_container_cluster.tests"]
}
output "insights-public-ip" {
value = "${data.external.insights-public-ip.result}"
}
And this is test-jq.sh (test cause is the first time I've used :S), the script I'm calling to print out in json format the data.
#!/bin/bash
#test-jq.sh
set -e
MyPublicIP=$(kubectl get services --all-namespaces | grep insights | grep LoadBalancer | awk '{print $5}')
jq -n --arg foobaz "$MyPublicIP" '{"extvar":$foobaz}'