blob: 1ec3cd9364c7f4f174f9d08cbe8459e3bf611bed [file] [log] [blame]
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Set of common operations that CI needs to invoke when using Kubernetes.
# The operations can be invoked using a provided kubeconfig file
# and kubernetes namespace.
#
# Specify the following environment variables to override defaults:
# - KUBECONFIG: path to .kube/config file (default: $HOME/.kube/config)
# - KUBERNETES_NAMESPACE: namespace to be used (default: default)
set -euxo pipefail
KUBECONFIG="${KUBECONFIG:=$HOME/.kube/config}"
KUBERNETES_NAMESPACE="${KUBERNETES_NAMESPACE:=default}"
KUBECTL="kubectl --kubeconfig=$KUBECONFIG --namespace=$KUBERNETES_NAMESPACE"
function retry() {
local command=$1
local max_retries=$2
local sleep_time=$3
for ((i = 1; i <= max_retries; i++)); do
local output
output=$(eval "${command}")
local status=$?
if [[ ${status} == 0 ]] && [[ -n ${output} ]]; then
echo "${output}"
return 0
fi
if [[ $i == "${max_retries}" ]]; then
echo "Command failed after ${max_retries} retries" >&2
return 1
fi
sleep "${sleep_time}"
done
}
# Invokes "kubectl apply" using specified kubeconfig and namespace.
#
# Usage: ./kubernetes.sh apply <path to .yaml file or directory with .yaml files>
function apply() {
eval "$KUBECTL apply -R -f $1"
}
# Invokes "kubectl delete" using specified kubeconfig and namespace.
#
# Usage: ./kubernetes.sh delete <path to .yaml file>
function delete() {
eval "$KUBECTL delete -R -f $1"
}
# Creates a namespace.
#
# Usage: ./kubernetes.sh createNamespace <namespace name>
function createNamespace() {
eval "kubectl --kubeconfig=${KUBECONFIG} create namespace $1"
}
# Deletes whole namespace with all its contents.
#
# Usage: ./kubernetes.sh deleteNamespace <namespace name>
function deleteNamespace() {
eval "kubectl --kubeconfig=${KUBECONFIG} delete namespace $1"
}
# Gets Load Balancer Ingress IP address.
# Blocks and retries until the IP is present or retry limit is exceeded.
#
# Usage: ./kubernetes.sh loadBalancerIP <name of the load balancer service>
function loadBalancerIP() {
local name=$1
local command="$KUBECTL get svc $name -ojsonpath='{.status.loadBalancer.ingress[0].ip}'"
retry "${command}" 36 10
}
# Gets Available NodePort to avoid conflicts with already allocated ports
#
# Usage: ./kubernetes.sh getAvailablePort <low range port> <high range port>
function getAvailablePort() {
local lowRangePort=$(($1 + 1)) #not inclusive low range
local highRangePort=$2
local used=false
local command="$KUBECTL get svc --all-namespaces -o \
go-template='{{range .items}}{{range.spec.ports}}{{if .nodePort}}{{.nodePort}}{{\"\n\"}}{{end}}{{end}}{{end}}'"
local usedPorts
usedPorts=$(eval "${command}")
local availablePort=$lowRangePort
for i in $(seq $lowRangePort $highRangePort);
do
while IFS= read -r usedPort; do
if [ "$i" = "$usedPort" ]; then
used=true
break
fi
done <<< "$usedPorts"
if $used; then
availablePort=$((availablePort + 1))
used=false
else
echo $availablePort
return 0
fi
echo $availablePort
done
}
#Waits until a designated job finish to continue the workflow execution
#Usage: ./kubernetes.sh waitForJob <kubernetes job name> <timeout i.e: 30m, 20s etc.>
function waitForJob(){
echo "Waiting for job completion..."
jobName=$1
eval "$KUBECTL wait --for=condition=complete --timeout=$2 $jobName"
echo "Job completed"
}
"$@"