mirror of
https://github.com/hanzozt/zt.git
synced 2026-10-30 15:04:55 +00:00
Upstream changes include: - Add get/set db version commands (#3579) - Fix link dial race condition (#3566) - Update channel version to v4.3.5 - Retire ingress-nginx in favor of Traefik (#3582) - Appease golangci-lint (#3594) - Fix flaky certchecker and link tests - Enable verbose logging for Go SDK apps - Improve router quickstart crash recovery Conflicts resolved keeping hanzozt branding while incorporating all upstream code improvements.
1311 lines
46 KiB
Bash
Executable File
1311 lines
46 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -o errexit
|
|
set -o nounset
|
|
set -o pipefail
|
|
|
|
checkBashVersion() {
|
|
if (( "${BASH_VERSION%%.*}" < 4 )); then
|
|
echo "This script requires Bash major version 4 or greater."
|
|
echo "Detected version: $BASH_VERSION"
|
|
if [[ ${OSTYPE:-} =~ [Dd]arwin ]]; then
|
|
echo -e "\nOn macOS, you can install bash with Homebrew:"
|
|
echo "brew install bash"
|
|
echo -e "\nThen run:"
|
|
#shellcheck disable=SC2016
|
|
echo '"$(brew --prefix bash)/bin/bash" ./minizt.bash ...'
|
|
fi
|
|
exit 1;
|
|
fi
|
|
}
|
|
|
|
banner(){
|
|
|
|
local profile="${1-}"
|
|
|
|
cat <<BANNER
|
|
__ ___
|
|
|\/| | |\ | | / | | |
|
|
| | | | \| | /_ | | |
|
|
|
|
BANNER
|
|
|
|
if [[ -n "$profile" && "$profile" != "minizt" ]]; then
|
|
echo -e " .: $* :.\n"
|
|
fi
|
|
}
|
|
|
|
_usage(){
|
|
if (( $# )); then
|
|
echo -e "\nERROR: unexpected arg '$1'" >&2
|
|
else
|
|
banner
|
|
fi
|
|
echo -e "\n Basic Commands:\n"\
|
|
" start\t\tstart minizt\n"\
|
|
" delete\t\tdelete minizt\n"\
|
|
" console\t\topen zt-console in browser\n"\
|
|
" creds\t\tprints admin user updb credentials\n"\
|
|
" status\t\tprint zt component status\n"\
|
|
" zt\t\tzt cli wrapper\n"\
|
|
" help\t\tshow these usage hints\n"\
|
|
"\n Profile Commands:\n"\
|
|
" profile list\tlist available profiles\n"\
|
|
" profile show\tshow default profile\n"\
|
|
" profile use\t\tset default profile\n"\
|
|
"\n Advanced Commands:\n"\
|
|
" shell\t\trun interactive shell inside the zt-controller container\n"\
|
|
" login\t\trun local zt binary edge login\n"\
|
|
"\n Other Commands:\n"\
|
|
" kubectl\t\tkubectl cli wrapper\n"\
|
|
" minikube\t\tminikube cli wrapper\n"\
|
|
"\n Options:\n"\
|
|
" --quiet\t\tsuppress INFO messages\n"\
|
|
" --verbose\t\tshow DEBUG messages\n"\
|
|
" --profile\t\tMINIKUBE_PROFILE (minizt)\n"\
|
|
" --namespace\t\tZITI_NAMESPACE (MINIKUBE_PROFILE)\n"\
|
|
" --no-hosts\t\tdon't use local hosts DB; use wildcard DNS zone based on minikube node IP\n"\
|
|
" --modify-hosts\tadd entries to local hosts database. Requires sudo if not running as root. Linux only.\n"\
|
|
"\n Debug:\n"\
|
|
" --charts\t\tZITI_CHARTS_REF (hanzozt) alternative charts repo\n"\
|
|
" --values-dir\tEXTRA_VALUES_DIR with Helm values files named zt-controller.yaml or zt-router.yaml\n"\
|
|
" --devel\t\tinclude Helm chart prereleases (passes --devel to Hanzo ZT chart installs/upgrades)\n"\
|
|
" --now\t\teliminate safety waits, e.g., before deleting minizt\n"\
|
|
" --\t\t\tMINIKUBE_START_ARGS args after -- passed to minikube start\n"
|
|
}
|
|
|
|
_usageProfileUse(){
|
|
echo -e "\nSet minizt default profile\n"\
|
|
"\n Usage:\n"\
|
|
" zt profile use [profile]\n"
|
|
}
|
|
|
|
_usageProfile(){
|
|
if (( $# )); then
|
|
echo -e "\nERROR: unexpected arg '$1'" >&2
|
|
fi
|
|
|
|
echo -e "\nProfile management commands\n"\
|
|
"\n Usage:\n"\
|
|
" zt profile [command]\n"\
|
|
"\n Available Commands:\n"\
|
|
" list\tlist available profiles\n"\
|
|
" show\tshow default profile\n"\
|
|
" use\t\tset minizt profile\n"
|
|
}
|
|
|
|
checkDns(){
|
|
# only param is an IPv4
|
|
[[ $# -eq 1 && $1 =~ ([0-9]{1,3}\.){3}[0-9]{1,3} ]] || {
|
|
logError "need IPv4 of minizt ingress as only param to checkDns()"
|
|
return 1
|
|
}
|
|
logDebug "checking dns to ensure ${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE} resolves to $1"
|
|
if grep -qE "^${1//./\\.}.*${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}" /etc/hosts \
|
|
|| nslookup "${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}" | grep -q "${1//./\\.}"; then
|
|
logDebug "host dns found expected minikube ingress IP '$1'"
|
|
return 0
|
|
else
|
|
logError "${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE} does not resolve to '$1'. Did you add the record in /etc/hosts?"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
deleteMinizt(){
|
|
local WAIT=30
|
|
if [[ $1 =~ ^[0-9]+$ ]]; then
|
|
WAIT="$1"
|
|
shift
|
|
else
|
|
logDebug "no integer param detected to deleteMinizt(), using default wait time ${WAIT}s"
|
|
fi
|
|
(( SAFETY_WAIT )) && {
|
|
logWarn "deleting ${MINIKUBE_PROFILE} in ${WAIT}s, use --now to skip wait" >&2
|
|
sleep "$WAIT"
|
|
}
|
|
logInfo "waiting for ${MINIKUBE_PROFILE} to be deleted"
|
|
minikube --profile "${MINIKUBE_PROFILE}" delete >&3
|
|
}
|
|
|
|
detectOs(){
|
|
if grep -qi "microsoft" /proc/sys/kernel/osrelease 2>/dev/null; then
|
|
logDebug "detected Windows OS"
|
|
echo "Windows"
|
|
elif [[ ${OSTYPE:-} =~ [Dd]arwin ]]; then
|
|
logDebug "detected macOS OS"
|
|
echo "macOS"
|
|
elif [[ ${OSTYPE:-} =~ [Ll]inux ]]; then
|
|
logDebug "detected Linux OS"
|
|
echo "Linux"
|
|
else
|
|
logError "failed to detect OS"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
makeMiniztStateDir() {
|
|
case "$DETECTED_OS" in
|
|
macOS)
|
|
state_dir="${XDG_STATE_DIR:-$HOME/Library/Application Support}/minizt"
|
|
;;
|
|
Linux|Windows)
|
|
state_dir="${XDG_STATE_DIR:-$HOME/.local/state}/minizt"
|
|
;;
|
|
*)
|
|
logError "Unknown os: $DETECTED_OS"
|
|
exit 1
|
|
esac
|
|
|
|
if [[ ! -d "$state_dir" ]]; then
|
|
logDebug "Creating minizt state directory: $state_dir"
|
|
mkdir -p "$state_dir"
|
|
fi
|
|
|
|
echo "$state_dir"
|
|
}
|
|
|
|
getZitiCliHome() {
|
|
case "$DETECTED_OS" in
|
|
Linux) echo "$HOME/.config/zt" ;;
|
|
*) echo "$HOME/.zt" ;;
|
|
esac
|
|
}
|
|
|
|
pathToNative() {
|
|
local path="$1"
|
|
case "$DETECTED_OS" in
|
|
Windows) wslpath -w "$path" ;;
|
|
*) echo "$path" ;;
|
|
esac
|
|
}
|
|
|
|
testClusterDns(){
|
|
if kubectlWrapper run "dnstest" --rm --tty --stdin --image busybox --restart Never -- \
|
|
nslookup "${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}" | grep "$1" >&3; then
|
|
logInfo "cluster dns test succeeded"
|
|
else
|
|
logError "cluster dns test failed"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
validateDnsName(){
|
|
if ! [[ $# -eq 1 ]]; then
|
|
logError "validateDnsName() takes one string param"
|
|
return 1
|
|
fi
|
|
if grep -qE '^[a-zA-Z0-9]([-a-zA-Z0-9]{2,251})[a-zA-Z0-9]$' <<<"$1"; then
|
|
logDebug "'$1' is a valid DNS name"
|
|
return 0
|
|
else
|
|
logError "'$1' could not be validated as an unqualified DNS name which is limited to at least four alphanumeric and hyphen characters and does not start nor end with a hyphen."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
checkSudoRequired() {
|
|
if (( EUID != 0 )); then
|
|
logInfo "sudo is required when not running as root"
|
|
fi
|
|
}
|
|
|
|
HOSTS_FILE='/etc/hosts'
|
|
|
|
cleanHosts() {
|
|
local marker="$1"
|
|
logWarn "Removing stale minizt entries from $HOSTS_FILE"
|
|
if (( EUID != 0 )); then
|
|
sudo sed -i "/$marker/d" "$HOSTS_FILE"
|
|
else
|
|
sed -i "/$marker/d" "$HOSTS_FILE"
|
|
fi
|
|
}
|
|
|
|
installHosts() {
|
|
hosts=(
|
|
"${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}"
|
|
"${MINIZITI_ROUTER_NAME}.${MINIZITI_INGRESS_ZONE}"
|
|
)
|
|
|
|
hosts_line="$MINIKUBE_NODE_EXTERNAL ${hosts[*]}"
|
|
|
|
if ! grep -q "$hosts_line" "$HOSTS_FILE"; then
|
|
|
|
checkSudoRequired
|
|
|
|
if grep -q "$MINIZITI_INGRESS_ZONE" "$HOSTS_FILE"; then
|
|
cleanHosts "$MINIZITI_INGRESS_ZONE"
|
|
fi
|
|
|
|
logInfo "Adding minizt entries to $HOSTS_FILE"
|
|
if (( EUID != 0 )); then
|
|
echo "$hosts_line" | sudo tee -a "$HOSTS_FILE" > /dev/null
|
|
else
|
|
echo "$hosts_line" | tee -a "$HOSTS_FILE" > /dev/null
|
|
fi
|
|
fi
|
|
}
|
|
|
|
getAdminSecret() {
|
|
kubectlWrapper get secrets "zt-controller-admin-secret" \
|
|
--namespace "$ZITI_NAMESPACE" \
|
|
--output go-template='{{index .data "admin-password" | base64decode }}'
|
|
}
|
|
|
|
showAdminCreds() {
|
|
logInfo "The password for 'admin' is: '$(getAdminSecret)'"
|
|
}
|
|
|
|
getConfigMapKey() {
|
|
local configmap="$1"
|
|
local key="$2"
|
|
kubectlWrapper get configmap "$configmap" \
|
|
--ignore-not-found=true \
|
|
--output jsonpath="{.data.$key}" 2> /dev/null
|
|
}
|
|
|
|
getIngressZone() {
|
|
local ingress_zone
|
|
local traefik_lb_ip
|
|
|
|
ingress_zone="$(getConfigMapKey "$MINIZITI_CONFIGMAP" 'ingress-zone')"
|
|
if [[ -z "$ingress_zone" ]]; then
|
|
logError "Failed to retrieve ingress zone. Did you start profile '$MINIKUBE_PROFILE' successfully?"
|
|
exit 1
|
|
elif [[ "$ingress_zone" =~ \.sslip\.io$ ]]; then
|
|
# For no-hosts mode, prefer the currently assigned Traefik LB IP in case
|
|
# a stale configmap still points at the minikube node IP.
|
|
traefik_lb_ip=$(kubectlWrapper get service traefik -n traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2> /dev/null || true)
|
|
if [[ -n "$traefik_lb_ip" ]]; then
|
|
ingress_zone="${traefik_lb_ip}.sslip.io"
|
|
fi
|
|
else
|
|
echo "$ingress_zone"
|
|
return
|
|
fi
|
|
|
|
echo "$ingress_zone"
|
|
}
|
|
|
|
miniztLogin() {
|
|
checkCommand zt
|
|
ingress_zone="$(getIngressZone)"
|
|
getAdminSecret | xargs zt edge login "https://${ZITI_NETWORK_NAME}.${ingress_zone}:443/edge/management/v1" \
|
|
--cli-identity "$MINIKUBE_PROFILE" \
|
|
--yes \
|
|
--username "admin" \
|
|
--password
|
|
|
|
logInfo "Setting default zt identity to: $MINIKUBE_PROFILE"
|
|
zt edge use "$MINIKUBE_PROFILE" >&3
|
|
}
|
|
|
|
miniztConsole() {
|
|
ingress_zone="$(getIngressZone)"
|
|
console_url="https://${ZITI_NETWORK_NAME}.${ingress_zone}/zac/"
|
|
case "$DETECTED_OS" in
|
|
"Windows")
|
|
checkCommand wslview
|
|
wslview "$console_url"
|
|
;;
|
|
"macOS")
|
|
checkCommand open
|
|
open "$console_url"
|
|
;;
|
|
*)
|
|
checkCommand xdg-open
|
|
xdg-open "$console_url"
|
|
;;
|
|
esac
|
|
logInfo "Opening zt-console: $console_url ..."
|
|
}
|
|
|
|
listProfiles() {
|
|
dir --format=single-column --ignore=default --sort=time --reverse "$PROFILES_DIR"
|
|
}
|
|
|
|
logger() {
|
|
local caller="${FUNCNAME[1]}"
|
|
|
|
if (( $# < 1 )); then
|
|
echo "ERROR: $caller() takes 1 or more args" >&2
|
|
return 1
|
|
fi
|
|
|
|
local message="$*"
|
|
|
|
if [[ "$message" =~ ^r\'(.+)\'$ ]]; then
|
|
raw_message="${BASH_REMATCH[1]}"
|
|
message="$raw_message"
|
|
fi
|
|
|
|
caller_level="${caller##log}"
|
|
if (( MINIZITI_DEBUG )); then
|
|
line="${caller_level^^} ${FUNCNAME[2]}:${BASH_LINENO[1]}: $message"
|
|
else
|
|
line="${caller_level^^} $message"
|
|
fi
|
|
|
|
if [[ -n "${raw_message-}" ]]; then
|
|
echo -E "$line"
|
|
else
|
|
echo -e "$line"
|
|
fi
|
|
}
|
|
|
|
logInfo() {
|
|
logger "$*"
|
|
}
|
|
|
|
logWarn() {
|
|
logger "$*" >&2
|
|
}
|
|
|
|
logError() {
|
|
logger "$*" >&2
|
|
}
|
|
|
|
logDebug() {
|
|
logger "$*" >&3
|
|
}
|
|
|
|
controllerPod() {
|
|
kubectlWrapper get pods \
|
|
--selector app.kubernetes.io/component=zt-controller \
|
|
--output jsonpath='{.items[0].metadata.name}'
|
|
}
|
|
|
|
getPodStatus() {
|
|
local pod_name="$1"
|
|
kubectlWrapper get pod \
|
|
--selector app.kubernetes.io/component="$pod_name" \
|
|
--ignore-not-found=true \
|
|
--output jsonpath='{.items[0].status.phase}' 2> /dev/null
|
|
}
|
|
|
|
showStatus() {
|
|
COMPONENTS=("zt-controller" "zt-router")
|
|
for component in "${COMPONENTS[@]}"; do
|
|
status="$(getPodStatus "$component")"
|
|
if [[ -z "$status" ]]; then
|
|
logError "Could not retrieve status for component $component"
|
|
exit 1
|
|
fi
|
|
echo "$component: $status"
|
|
done
|
|
}
|
|
|
|
getDefaultProfile() {
|
|
default_profile="$DEFAULT_PROFILE"
|
|
if [[ -L "$default_profile" ]]; then
|
|
basename "$(realpath "$default_profile")"
|
|
else
|
|
echo "minizt"
|
|
fi
|
|
}
|
|
|
|
setProfile() {
|
|
profile="$1"
|
|
profiles="$(listProfiles)"
|
|
if ! echo "$profiles" | grep -q "$profile"; then
|
|
logError "Invalid profile: $profile\nValid profiles are:\n$profiles"
|
|
exit 1
|
|
else
|
|
ln -nsf "$PROFILES_DIR/$profile" "$DEFAULT_PROFILE"
|
|
logInfo "Set default profile to: '$profile'"
|
|
fi
|
|
}
|
|
|
|
ztWrapper() {
|
|
kubectlWrapper exec "$(controllerPod)" --container zt-controller -- ztLogin > /dev/null
|
|
kubectlWrapper exec "$(controllerPod)" --container zt-controller -- zt "$@"
|
|
}
|
|
|
|
shellWrapper() {
|
|
kubectlWrapper exec "$(controllerPod)" --container zt-controller --tty --stdin -- bash
|
|
}
|
|
|
|
kubectlWrapper() {
|
|
minikube kubectl --profile "$MINIKUBE_PROFILE" -- --context "$MINIKUBE_PROFILE" "$@"
|
|
}
|
|
|
|
minikubeWrapper() {
|
|
minikube --profile "$MINIKUBE_PROFILE" "$@"
|
|
}
|
|
|
|
helmWrapper() {
|
|
helm --kube-context "$MINIKUBE_PROFILE" "$@"
|
|
}
|
|
|
|
checkCommand() {
|
|
if ! command -v "$1" &>/dev/null; then
|
|
logError "this script requires command '$1'. Please install on the search PATH and try again."
|
|
$1
|
|
fi
|
|
}
|
|
|
|
main(){
|
|
# xtrace opt implies --verbose
|
|
if [[ $- =~ x ]]; then
|
|
MINIZITI_DEBUG=1
|
|
exec 3>&1
|
|
else
|
|
MINIZITI_DEBUG=0
|
|
fi
|
|
|
|
checkBashVersion >&2
|
|
|
|
# require commands
|
|
declare -a BINS=(awk grep helm jq minikube nslookup pgrep sed xargs)
|
|
for BIN in "${BINS[@]}"; do
|
|
checkCommand "$BIN"
|
|
done
|
|
|
|
# open a descriptor for debug messages
|
|
exec 3>/dev/null
|
|
|
|
# local strings with defaults that never produce an error
|
|
declare DELETE_MINIZITI=0 \
|
|
DETECTED_OS \
|
|
DO_ZITI_LOGIN=0 \
|
|
HELM_INCLUDE_DEVEL=0 \
|
|
MINIKUBE_NODE_EXTERNAL \
|
|
MINIKUBE_PROFILE \
|
|
MINIZITI_HOSTS=1 \
|
|
MINIZITI_MODIFY_HOSTS=0 \
|
|
OPEN_ZITI_CONSOLE=0 \
|
|
RUN_ZITI_CLI=0 \
|
|
SAFETY_WAIT=1 \
|
|
SHOW_ADMIN_CREDS=0 \
|
|
START_MINIZITI=0 \
|
|
ZITI_CHARTS_ALT=0 \
|
|
ZITI_CHARTS_REF="hanzozt" \
|
|
ZITI_CHARTS_URL="https://hanzozt.io/helm-charts/charts" \
|
|
EXTRA_VALUES_DIR \
|
|
ZITI_NAMESPACE
|
|
|
|
# local arrays with defaults that never produce an error
|
|
declare -a MINIKUBE_START_ARGS=()
|
|
|
|
# local defaults that are inherited or may error
|
|
DETECTED_OS="$(detectOs)"
|
|
: "${DEBUG_MINIKUBE_TUNNEL:=0}" # set env = 1 to trigger the minikube tunnel probe
|
|
: "${MINIZITI_TIMEOUT_SECS:=240}"
|
|
: "${ZITI_NETWORK_NAME:=minizt-controller}"
|
|
MINIZITI_CONFIGMAP="minizt-config"
|
|
ZITI_CLI_HOME="$(getZitiCliHome)"
|
|
ZITI_CLI_CERTS_DIR="$ZITI_CLI_HOME/certs"
|
|
STATE_DIR="$(makeMiniztStateDir)"
|
|
PROFILES_DIR="$STATE_DIR/profiles"
|
|
[[ ! -d "$PROFILES_DIR" ]] && mkdir "$PROFILES_DIR"
|
|
DEFAULT_PROFILE="$PROFILES_DIR/default"
|
|
|
|
MINIKUBE_PROFILE="$(getDefaultProfile)"
|
|
|
|
while (( $# )); do
|
|
case "$1" in
|
|
start) START_MINIZITI=1
|
|
shift
|
|
;;
|
|
delete) DELETE_MINIZITI=1
|
|
shift
|
|
;;
|
|
console) OPEN_ZITI_CONSOLE=1
|
|
shift
|
|
;;
|
|
creds) SHOW_ADMIN_CREDS=1
|
|
shift
|
|
;;
|
|
profile)
|
|
shift
|
|
if (( $# == 0 )); then
|
|
_usageProfile
|
|
exit 1
|
|
fi
|
|
case "$1" in
|
|
list)
|
|
shift
|
|
listProfiles
|
|
exit
|
|
;;
|
|
use)
|
|
shift
|
|
if (( $# != 1 )); then
|
|
_usageProfileUse
|
|
exit 1
|
|
fi
|
|
setProfile "$1"
|
|
exit
|
|
;;
|
|
show)
|
|
getDefaultProfile
|
|
exit
|
|
;;
|
|
*)
|
|
_usageProfile "$1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
login) DO_ZITI_LOGIN=1
|
|
shift
|
|
;;
|
|
status)
|
|
showStatus
|
|
exit
|
|
;;
|
|
zt) RUN_ZITI_CLI=1
|
|
shift
|
|
zt_cli_args=("$@")
|
|
shift "${#zt_cli_args[@]}"
|
|
;;
|
|
kubectl) shift
|
|
kubectlWrapper "${@:-}"
|
|
exit
|
|
;;
|
|
minikube) shift
|
|
minikubeWrapper "${@:-}"
|
|
exit
|
|
;;
|
|
shell) shift
|
|
shellWrapper "${@:-}"
|
|
exit
|
|
;;
|
|
-p|--profile) validateDnsName "$2"
|
|
MINIKUBE_PROFILE="$2"
|
|
# sanity check the profile name input
|
|
if [[ ${MINIKUBE_PROFILE} =~ ^- ]]; then
|
|
# in case the arg value is another option instead of the profile name
|
|
logError "--profile needs a profile name not starting with a hyphen"
|
|
_usage
|
|
exit 1
|
|
fi
|
|
|
|
shift 2
|
|
;;
|
|
-n|--namespace) ZITI_NAMESPACE="$2"
|
|
shift 2
|
|
;;
|
|
--charts) ZITI_CHARTS_REF="${2%"/"}"
|
|
ZITI_CHARTS_URL="${2%"/"}"
|
|
ZITI_CHARTS_ALT=1
|
|
shift 2
|
|
;;
|
|
--values-dir) EXTRA_VALUES_DIR="${2%"/"}"
|
|
shift 2
|
|
;;
|
|
--devel) HELM_INCLUDE_DEVEL=1
|
|
shift
|
|
;;
|
|
-q|--quiet) exec > /dev/null
|
|
shift
|
|
;;
|
|
-v|--verbose|--debug)
|
|
MINIZITI_DEBUG=1
|
|
exec 3>&1
|
|
shift
|
|
;;
|
|
--now) SAFETY_WAIT=0
|
|
shift
|
|
;;
|
|
--no-hosts) MINIZITI_HOSTS=0
|
|
shift
|
|
;;
|
|
--modify-hosts) if [[ "$DETECTED_OS" != "Linux" ]]; then
|
|
logError "The '--modify-hosts' option is only available for Linux"
|
|
exit 1
|
|
fi
|
|
MINIZITI_MODIFY_HOSTS=1
|
|
shift
|
|
;;
|
|
--) shift
|
|
mapfile -t -n1 MINIKUBE_START_ARGS <<< "$*"
|
|
shift $#
|
|
if (( ${#MINIKUBE_START_ARGS[*]} )) && [[ -n "${MINIKUBE_START_ARGS[0]}" ]]; then
|
|
logDebug "passing ${#MINIKUBE_START_ARGS[*]} args to minikube start: '${MINIKUBE_START_ARGS[*]}'"
|
|
else
|
|
MINIKUBE_START_ARGS=()
|
|
fi
|
|
;;
|
|
-h|*help) _usage
|
|
exit 0
|
|
;;
|
|
*) _usage "$1"
|
|
exit
|
|
;;
|
|
esac
|
|
done
|
|
|
|
: "${ZITI_NAMESPACE:=${MINIKUBE_PROFILE}}"
|
|
|
|
MINIZITI_INGRESS_ZONE="$MINIKUBE_PROFILE.internal"
|
|
MINIZITI_INTERCEPT_ZONE="$MINIKUBE_PROFILE.private"
|
|
PROFILE_DIR="$PROFILES_DIR/${MINIKUBE_PROFILE}"
|
|
IDENTITIES_DIR="$PROFILE_DIR/identities"
|
|
|
|
if (( DO_ZITI_LOGIN )); then
|
|
miniztLogin
|
|
exit 0
|
|
fi
|
|
|
|
if (( SHOW_ADMIN_CREDS )); then
|
|
showAdminCreds
|
|
exit 0
|
|
fi
|
|
|
|
if (( OPEN_ZITI_CONSOLE )); then
|
|
miniztConsole
|
|
exit 0
|
|
fi
|
|
|
|
if (( RUN_ZITI_CLI )); then
|
|
ztWrapper "${zt_cli_args[@]}"
|
|
exit 0
|
|
fi
|
|
|
|
if (( DELETE_MINIZITI )); then
|
|
banner "$MINIKUBE_PROFILE"
|
|
|
|
trap EXIT
|
|
if ingress_zone="$(getIngressZone)"; then
|
|
if (( MINIZITI_MODIFY_HOSTS )) && grep -q "$ingress_zone" "$HOSTS_FILE"; then
|
|
checkSudoRequired
|
|
cleanHosts "$ingress_zone"
|
|
fi
|
|
|
|
CERT_FILE="$(find "$ZITI_CLI_CERTS_DIR" -maxdepth 1 -type f -name "${ZITI_NETWORK_NAME}.$ingress_zone" -print -quit 2> /dev/null)"
|
|
if [[ -n "$CERT_FILE" ]]; then
|
|
logWarn "Deleting minizt certificate file: $CERT_FILE"
|
|
rm -f "$CERT_FILE"
|
|
fi
|
|
fi
|
|
trap - EXIT
|
|
|
|
deleteMinizt 10
|
|
|
|
if [[ -d "$PROFILE_DIR" ]]; then
|
|
logWarn "Deleting minizt profile directory: $PROFILE_DIR"
|
|
rm -rf "$PROFILE_DIR"
|
|
fi
|
|
|
|
if [[ -L "$DEFAULT_PROFILE" ]]; then
|
|
if [[ "$(basename "$(realpath "$DEFAULT_PROFILE")")" == "$MINIKUBE_PROFILE" ]]; then
|
|
unlink "$DEFAULT_PROFILE"
|
|
fi
|
|
fi
|
|
|
|
# Cannot nicely call logout until https://github.com/hanzozt/zt/issues/1305 is addressed.
|
|
# if checkCommand zt &>/dev/null; then
|
|
# logWarn "Removing $MINIKUBE_PROFILE profile identity from zt-cli.json"
|
|
# zt edge logout --cli-identity "$MINIKUBE_PROFILE" >&3
|
|
# fi
|
|
|
|
exit 0
|
|
fi
|
|
|
|
if (( START_MINIZITI != 1 )); then
|
|
_usage
|
|
exit 0;
|
|
fi
|
|
|
|
|
|
banner "$MINIKUBE_PROFILE"
|
|
|
|
if [[ ! -d "$IDENTITIES_DIR" ]]; then
|
|
logDebug "Creating minizt identities directory: ($IDENTITIES_DIR)"
|
|
mkdir -p "$IDENTITIES_DIR"
|
|
fi
|
|
|
|
#
|
|
## Ensure Minikube is Started and Configured
|
|
#
|
|
|
|
# run 'minikube start' if not running or any extra start args are present
|
|
logInfo "waiting for minikube to be ready"
|
|
if ! minikube status \
|
|
--profile "${MINIKUBE_PROFILE}" 2>/dev/null \
|
|
| grep -q "apiserver: Running" \
|
|
|| (( ${#MINIKUBE_START_ARGS[*]} )); then
|
|
logDebug "apiserver not running or got extra start args, running 'minikube start'"
|
|
eval minikube start \
|
|
--profile "${MINIKUBE_PROFILE}" \
|
|
"${MINIKUBE_START_ARGS[*]}" >&3
|
|
else
|
|
logDebug "apiserver is running, not starting minikube"
|
|
fi
|
|
|
|
MINIKUBE_NODE_EXTERNAL=$(minikube --profile "${MINIKUBE_PROFILE}" ip)
|
|
# if --no-hosts then build a new zone name for RFC-1918 wildcard DNS
|
|
(( MINIZITI_HOSTS )) || {
|
|
MINIZITI_INGRESS_ZONE="${MINIKUBE_NODE_EXTERNAL}.sslip.io"
|
|
logDebug "DNS wildcard zone for ingresses is ${MINIZITI_INGRESS_ZONE}"
|
|
}
|
|
|
|
if [[ -n "${MINIKUBE_NODE_EXTERNAL:-}" ]]; then
|
|
logDebug "the minikube external IP is ${MINIKUBE_NODE_EXTERNAL}"
|
|
else
|
|
logError "failed to find minikube external IP"
|
|
exit 1
|
|
fi
|
|
|
|
if (( MINIZITI_MODIFY_HOSTS )); then
|
|
installHosts
|
|
fi
|
|
|
|
# verify current context can connect to apiserver
|
|
kubectlWrapper cluster-info >&3
|
|
logDebug "kubectl successfully obtained cluster-info from apiserver"
|
|
|
|
# ingress controller setup happens after Helm repositories are configured.
|
|
|
|
declare -A HELM_REPOS
|
|
HELM_REPOS[hanzozt]="hanzozt.io/helm-charts"
|
|
HELM_REPOS[jetstack]="charts.jetstack.io"
|
|
HELM_REPOS[traefik]="traefik.github.io/charts"
|
|
for REPO in "${!HELM_REPOS[@]}"; do
|
|
if helmWrapper repo list | cut -f1 | grep -qE "^${REPO}(\s+)?$"; then
|
|
logDebug "refreshing ${REPO} Helm Charts"
|
|
helmWrapper repo update "${REPO}" >&3
|
|
else
|
|
logInfo "subscribing to ${REPO} Helm Charts"
|
|
helmWrapper repo add "${REPO}" "https://${HELM_REPOS[${REPO}]}" >&3
|
|
fi
|
|
done
|
|
|
|
# Enable minikube MetalLB so LoadBalancer services (e.g. Traefik) get an
|
|
# external IP without requiring a separate `minikube tunnel` step.
|
|
logInfo "ensuring minikube metallb addon is enabled"
|
|
minikubeWrapper addons enable metallb >&3
|
|
|
|
kubectlWrapper wait deployments \
|
|
--namespace metallb-system \
|
|
--for condition=Available=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" \
|
|
--all >&3
|
|
|
|
local metallb_pool_name
|
|
local metallb_pool_start
|
|
local metallb_pool_end
|
|
local existing_metallb_pool
|
|
local existing_metallb_legacy_pool
|
|
local existing_metallb_legacy_config
|
|
local existing_metallb_legacy_address
|
|
local traefik_lb_ip
|
|
metallb_pool_name=""
|
|
metallb_pool_start="${MINIKUBE_NODE_EXTERNAL%.*}.240"
|
|
metallb_pool_end="${MINIKUBE_NODE_EXTERNAL%.*}.250"
|
|
|
|
if kubectlWrapper get crd ipaddresspools.metallb.io >/dev/null 2>&1; then
|
|
existing_metallb_pool=$(kubectlWrapper get ipaddresspool -n metallb-system -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
|
|
if [[ -n "${existing_metallb_pool}" ]]; then
|
|
metallb_pool_name="${existing_metallb_pool}"
|
|
logInfo "using existing metallb IPAddressPool '${metallb_pool_name}'"
|
|
else
|
|
metallb_pool_name="miniziti-pool"
|
|
logInfo "configuring fallback metallb address pool ${metallb_pool_start}-${metallb_pool_end}"
|
|
cat <<EOF | kubectlWrapper apply -f - >&3
|
|
apiVersion: metallb.io/v1beta1
|
|
kind: IPAddressPool
|
|
metadata:
|
|
name: ${metallb_pool_name}
|
|
namespace: metallb-system
|
|
spec:
|
|
addresses:
|
|
- ${metallb_pool_start}-${metallb_pool_end}
|
|
---
|
|
apiVersion: metallb.io/v1beta1
|
|
kind: L2Advertisement
|
|
metadata:
|
|
name: ${metallb_pool_name}
|
|
namespace: metallb-system
|
|
spec:
|
|
ipAddressPools:
|
|
- ${metallb_pool_name}
|
|
EOF
|
|
fi
|
|
else
|
|
existing_metallb_legacy_config=$(kubectlWrapper get configmap -n metallb-system config -o jsonpath='{.data.config}' 2>/dev/null || true)
|
|
existing_metallb_legacy_pool=$(sed -n 's/^[[:space:]]*-[[:space:]]*name:[[:space:]]*\([^[:space:]]\+\).*$/\1/p' <<< "${existing_metallb_legacy_config}" | head -n1 || true)
|
|
existing_metallb_legacy_address=$(sed -n 's/^[[:space:]]*-[[:space:]]*\([^[:space:]]\+\).*$/\1/p' <<< "${existing_metallb_legacy_config}" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+-[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -n1 || true)
|
|
if [[ -n "${existing_metallb_legacy_pool}" && -n "${existing_metallb_legacy_address}" ]]; then
|
|
metallb_pool_name="${existing_metallb_legacy_pool}"
|
|
logInfo "using existing metallb legacy pool '${metallb_pool_name}'"
|
|
else
|
|
metallb_pool_name="miniziti-pool"
|
|
logInfo "configuring fallback metallb address pool ${metallb_pool_start}-${metallb_pool_end}"
|
|
# legacy addon path: use non-interactive configmap instead of
|
|
# `minikube addons configure metallb`, which prompts for stdin.
|
|
cat <<EOF | kubectlWrapper apply -f - >&3
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
namespace: metallb-system
|
|
name: config
|
|
data:
|
|
config: |
|
|
address-pools:
|
|
- name: ${metallb_pool_name}
|
|
protocol: layer2
|
|
addresses:
|
|
- ${metallb_pool_start}-${metallb_pool_end}
|
|
EOF
|
|
fi
|
|
fi
|
|
|
|
if kubectlWrapper get deployment "traefik" --namespace traefik >/dev/null 2>&1; then
|
|
logDebug "traefik is already installed"
|
|
else
|
|
logInfo "installing traefik"
|
|
local -a _traefik_cmd=(upgrade --install traefik traefik/traefik
|
|
--namespace traefik --create-namespace
|
|
--set providers.kubernetesCRD.enabled=true
|
|
--set service.type=LoadBalancer
|
|
)
|
|
helmWrapper "${_traefik_cmd[@]}" >&3
|
|
fi
|
|
|
|
logInfo "waiting for traefik to be ready"
|
|
kubectlWrapper wait deployments traefik \
|
|
--namespace traefik \
|
|
--for condition=Available=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
kubectlWrapper wait pods \
|
|
--namespace traefik \
|
|
--for condition=ready \
|
|
--selector app.kubernetes.io/name=traefik \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
logInfo "waiting for traefik LoadBalancer external IP"
|
|
for ((i=0; i<MINIZITI_TIMEOUT_SECS; i++)); do
|
|
traefik_lb_ip=$(kubectlWrapper get service traefik -n traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null || true)
|
|
[[ -n "${traefik_lb_ip}" ]] && break
|
|
sleep 1
|
|
done
|
|
if [[ -z "${traefik_lb_ip}" ]]; then
|
|
logError "traefik service external IP is still pending after ${MINIZITI_TIMEOUT_SECS}s"
|
|
logError "metallb pools:"; kubectlWrapper get ipaddresspool -n metallb-system >&2 || true
|
|
logError "metallb advertisements:"; kubectlWrapper get l2advertisement -n metallb-system >&2 || true
|
|
logError "traefik service:"; kubectlWrapper get service traefik -n traefik -o wide >&2 || true
|
|
exit 1
|
|
fi
|
|
logDebug "traefik LoadBalancer external IP is ${traefik_lb_ip}"
|
|
|
|
# In --no-hosts mode, route advertised hosts through the LoadBalancer IP
|
|
# instead of minikube node IP so routers use the same reachable north-south
|
|
# entrypoint as external clients.
|
|
if (( ! MINIZITI_HOSTS )); then
|
|
MINIZITI_INGRESS_ZONE="${traefik_lb_ip}.sslip.io"
|
|
logDebug "DNS wildcard zone for ingresses is ${MINIZITI_INGRESS_ZONE}"
|
|
fi
|
|
|
|
helmWrapper upgrade --install cert-manager jetstack/cert-manager \
|
|
--namespace cert-manager --create-namespace \
|
|
--set crds.enabled=true >&3
|
|
kubectlWrapper wait deployments -n cert-manager --for condition=Available --timeout="${MINIZITI_TIMEOUT_SECS}s" --all >&3
|
|
|
|
kubectlWrapper get namespace "${ZITI_NAMESPACE}" &>/dev/null || kubectlWrapper create namespace "${ZITI_NAMESPACE}" >&3
|
|
helmWrapper upgrade --install trust-manager jetstack/trust-manager \
|
|
--namespace cert-manager \
|
|
--set crds.keep=false \
|
|
--set app.trust.namespace="${ZITI_NAMESPACE}" >&3
|
|
# Wait for trust-manager-tls secret to be created by cert-manager
|
|
logInfo "waiting for trust-manager-tls secret"
|
|
for ((i=0; i<MINIZITI_TIMEOUT_SECS; i++)); do
|
|
if kubectlWrapper get secret -n cert-manager trust-manager-tls >/dev/null 2>&1; then
|
|
logDebug "trust-manager-tls secret exists"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
kubectlWrapper wait deployments -n cert-manager --for condition=Available --timeout="${MINIZITI_TIMEOUT_SECS}s" trust-manager >&3
|
|
|
|
# Wait for trust-manager pods to be ready (not just deployment available)
|
|
logInfo "waiting for trust-manager pods to be ready"
|
|
kubectlWrapper wait pods -n cert-manager -l app.kubernetes.io/name=trust-manager --for condition=Ready --timeout="${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
# Wait for trust-manager webhook endpoint to actually be responsive
|
|
# Pod Ready doesn't guarantee the webhook service endpoint is registered and accepting connections
|
|
logInfo "waiting for trust-manager webhook to be responsive"
|
|
for ((i=0; i<MINIZITI_TIMEOUT_SECS; i++)); do
|
|
# Check if endpoints are registered for the trust-manager service
|
|
local endpoints
|
|
endpoints=$(kubectlWrapper get endpoints -n cert-manager trust-manager -o jsonpath='{.subsets[*].addresses[*].ip}' 2>/dev/null || true)
|
|
if [[ -n "${endpoints}" ]]; then
|
|
logDebug "trust-manager endpoints registered: ${endpoints}"
|
|
# Give the webhook a moment to fully initialize after endpoint registration
|
|
sleep 3
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
#
|
|
## Ensure Hanzo ZT Controller is Upgraded and Ready
|
|
#
|
|
|
|
logInfo "installing hanzozt controller chart"
|
|
if (( ZITI_CHARTS_ALT )) && [[ -s "${ZITI_CHARTS_REF}/zt-controller/Chart.lock" ]]; then
|
|
helmWrapper dependency build "${ZITI_CHARTS_REF}/zt-controller" >&3
|
|
fi
|
|
local -a _controller_cmd=(upgrade --install "zt-controller" "${ZITI_CHARTS_REF}/zt-controller"
|
|
--namespace "${ZITI_NAMESPACE}" --create-namespace
|
|
--set clientApi.advertisedHost="${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}"
|
|
logInfo "installing hanzozt controller chart"
|
|
if (( ZITI_CHARTS_ALT )) && [[ -s "${ZITI_CHARTS_REF}/zt-controller/Chart.lock" ]]; then
|
|
helmWrapper dependency build "${ZITI_CHARTS_REF}/zt-controller" >&3
|
|
fi
|
|
local -a _controller_cmd=(upgrade --install "zt-controller" "${ZITI_CHARTS_REF}/zt-controller"
|
|
--namespace "${ZITI_NAMESPACE}" --create-namespace
|
|
--set clientApi.advertisedHost="${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}"
|
|
--values "${ZITI_CHARTS_URL}/zt-controller/values-traefik-ingressroutetcp.yaml"
|
|
)
|
|
if (( HELM_INCLUDE_DEVEL )) && (( ! ZITI_CHARTS_ALT )); then
|
|
_controller_cmd+=(--devel)
|
|
fi
|
|
if [[ -n "${EXTRA_VALUES_DIR:-}" && -s "${EXTRA_VALUES_DIR}/zt-controller.yaml" ]]; then
|
|
_controller_cmd+=(--values "${EXTRA_VALUES_DIR}/zt-controller.yaml")
|
|
fi
|
|
helmWrapper "${_controller_cmd[@]}" >&3
|
|
|
|
local web_identity_cert_name
|
|
web_identity_cert_name="zt-controller-web-identity-cert"
|
|
logInfo "waiting for cert-manager certificate '${web_identity_cert_name}' to be ready"
|
|
for ((i=0; i<MINIZITI_TIMEOUT_SECS; i++)); do
|
|
if kubectlWrapper get certificate.cert-manager.io "${web_identity_cert_name}" --namespace "${ZITI_NAMESPACE}" >/dev/null 2>&1; then
|
|
logDebug "certificate '${web_identity_cert_name}' exists"
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
kubectlWrapper wait certificate.cert-manager.io "${web_identity_cert_name}" \
|
|
--namespace "${ZITI_NAMESPACE}" \
|
|
--for condition=Ready=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
logInfo "restarting zt-controller deployment to reload reissued certificates"
|
|
kubectlWrapper rollout restart deployment/zt-controller \
|
|
--namespace "${ZITI_NAMESPACE}" >&3
|
|
|
|
logDebug "setting default namespace '${ZITI_NAMESPACE}' in kubeconfig context '${MINIKUBE_PROFILE}'"
|
|
kubectlWrapper config set-context "${MINIKUBE_PROFILE}" \
|
|
--namespace "${ZITI_NAMESPACE}" >&3
|
|
|
|
logInfo "waiting for zt-controller to be ready"
|
|
kubectlWrapper wait deployments zt-controller \
|
|
--namespace "${ZITI_NAMESPACE}" \
|
|
--for condition=Available=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
#
|
|
## Ensure Minikube Tunnel is Running on macOS and WSL
|
|
#
|
|
|
|
# wait to probe for the minikube tunnel until after controller deployment so there's at least one
|
|
# ingress causing minikube to immediately prompt for sudo password
|
|
if (( DEBUG_MINIKUBE_TUNNEL )) || [[ "${DETECTED_OS}" =~ Windows|macOS ]]; then
|
|
logDebug "detected OS is ${DETECTED_OS}, probing for minikube tunnel"
|
|
if ! pgrep -f "minikube --profile ${MINIKUBE_PROFILE} tunnel" >&3; then
|
|
echo -e "ERROR: ${DETECTED_OS} OS requires a running minikube tunnel for ingresses."\
|
|
" In another terminal, run the following command. Then re-run this script."\
|
|
"\n\n\tminikube --profile ${MINIKUBE_PROFILE} tunnel\n" >&2
|
|
exit 1
|
|
else
|
|
logDebug "minikube tunnel is running"
|
|
fi
|
|
# recommend /etc/hosts change unless dns is configured to reach the minikube node IP
|
|
checkDns "127.0.0.1"
|
|
else
|
|
checkDns "$MINIKUBE_NODE_EXTERNAL"
|
|
fi
|
|
|
|
#
|
|
## Ensure Cluster DNS is Resolving ${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}
|
|
#
|
|
|
|
if ! testClusterDns "${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}" 2>/dev/null; then
|
|
logDebug "initial cluster dns test failed, doing cluster dns setup"
|
|
|
|
# xargs trims whitespace because minikube ssh returns a stray trailing '\r' after remote command output
|
|
logDebug "probing minikube node for internal host record"
|
|
MINIKUBE_NODE_INTERNAL=$(minikube --profile "${MINIKUBE_PROFILE}" ssh 'grep host.minikube.internal /etc/hosts')
|
|
|
|
if [[ -n "${MINIKUBE_NODE_INTERNAL:-}" ]]; then
|
|
# strip surrounding whitespace
|
|
MINIKUBE_NODE_INTERNAL=$(xargs <<< "${MINIKUBE_NODE_INTERNAL}")
|
|
logDebug "the minikube internal host record is \"${MINIKUBE_NODE_INTERNAL}\""
|
|
else
|
|
logError "failed to find minikube internal IP"
|
|
exit 1
|
|
fi
|
|
|
|
(( MINIZITI_HOSTS )) && {
|
|
logDebug "patching coredns configmap with *.${MINIZITI_INGRESS_ZONE} forwarder to minikube node external IP"
|
|
kubectlWrapper patch configmap "coredns" \
|
|
--namespace kube-system \
|
|
--patch "
|
|
data:
|
|
Corefile: |
|
|
.:53 {
|
|
log
|
|
errors
|
|
health {
|
|
lameduck 5s
|
|
}
|
|
ready
|
|
kubernetes cluster.local in-addr.arpa ip6.arpa {
|
|
pods insecure
|
|
fallthrough in-addr.arpa ip6.arpa
|
|
ttl 30
|
|
}
|
|
prometheus :9153
|
|
hosts {
|
|
${MINIKUBE_NODE_INTERNAL}
|
|
fallthrough
|
|
}
|
|
forward . /etc/resolv.conf {
|
|
max_concurrent 1000
|
|
}
|
|
cache 30
|
|
loop
|
|
reload
|
|
loadbalance
|
|
}
|
|
${MINIZITI_INGRESS_ZONE}:53 {
|
|
errors
|
|
cache 30
|
|
forward . ${MINIKUBE_NODE_EXTERNAL}
|
|
}
|
|
" >&3
|
|
|
|
logDebug "deleting coredns pod so a new one will have modified Corefile"
|
|
kubectlWrapper delete pods \
|
|
--context "$MINIKUBE_PROFILE" \
|
|
--namespace kube-system \
|
|
--selector k8s-app=kube-dns >&3
|
|
|
|
logDebug "waiting for cluster dns to be ready"
|
|
kubectlWrapper wait deployments "coredns" \
|
|
--namespace kube-system \
|
|
--for condition=Available=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
}
|
|
|
|
# perform a DNS query in a pod so we know wildcard zone forwarding is working inside the cluster
|
|
testClusterDns "${MINIKUBE_NODE_EXTERNAL}"
|
|
fi
|
|
|
|
logInfo "Applying $MINIZITI_CONFIGMAP configmap"
|
|
cat <<EOF | kubectlWrapper apply -f - >&3
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: "$MINIZITI_CONFIGMAP"
|
|
namespace: "$ZITI_NAMESPACE"
|
|
data:
|
|
ingress-zone: "$MINIZITI_INGRESS_ZONE"
|
|
EOF
|
|
|
|
logInfo "Setting default zt identity to: $MINIKUBE_PROFILE"
|
|
ztWrapper edge use "$MINIKUBE_PROFILE" >&3
|
|
|
|
ROUTER_NAME='minizt-router'
|
|
ROUTER_OTT="$IDENTITIES_DIR/$ROUTER_NAME.jwt"
|
|
if ztWrapper edge list edge-routers "name=\"$ROUTER_NAME\"" \
|
|
| grep -q minizt-router; then
|
|
logDebug "updating $ROUTER_NAME"
|
|
ztWrapper edge update edge-router "$ROUTER_NAME" \
|
|
--role-attributes "public-routers" >&3
|
|
else
|
|
logDebug "creating $ROUTER_NAME"
|
|
ztWrapper edge create edge-router "$ROUTER_NAME" \
|
|
--role-attributes "public-routers" \
|
|
--tunneler-enabled >&3
|
|
ztWrapper edge list edge-routers \
|
|
"name=\"$ROUTER_NAME\"" \
|
|
--output-json \
|
|
| jq --exit-status --raw-output '.data[0].enrollmentJwt' > "$ROUTER_OTT"
|
|
fi
|
|
|
|
logDebug "installing router chart as 'zt-router'"
|
|
if (( ZITI_CHARTS_ALT )) && [[ -s "${ZITI_CHARTS_REF}/zt-router/Chart.lock" ]]; then
|
|
helmWrapper dependency build "${ZITI_CHARTS_REF}/zt-router" >&3
|
|
fi
|
|
local -a _router_cmd=(upgrade --install "zt-router" "${ZITI_CHARTS_REF}/zt-router"
|
|
--namespace "${ZITI_NAMESPACE}"
|
|
--set-file enrollmentJwt="$ROUTER_OTT"
|
|
--set edge.advertisedHost="minizt-router.${MINIZITI_INGRESS_ZONE}"
|
|
--set ctrl.endpoint="${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}:443"
|
|
--set "tunnel.mode=host"
|
|
--values "${ZITI_CHARTS_URL}/zt-router/values-traefik-ingressroutetcp.yaml"
|
|
--set linkListeners.transport.service.enabled=false
|
|
)
|
|
)
|
|
if (( HELM_INCLUDE_DEVEL )) && (( ! ZITI_CHARTS_ALT )); then
|
|
_router_cmd+=(--devel)
|
|
fi
|
|
if [[ -n "${EXTRA_VALUES_DIR:-}" && -s "${EXTRA_VALUES_DIR}/zt-router.yaml" ]]; then
|
|
_router_cmd+=(--values "${EXTRA_VALUES_DIR}/zt-router.yaml")
|
|
fi
|
|
helmWrapper "${_router_cmd[@]}" >&3
|
|
|
|
logInfo "waiting for zt-router to be ready"
|
|
kubectlWrapper wait deployments "zt-router" \
|
|
--namespace "${ZITI_NAMESPACE}" \
|
|
--for condition=Available=True \
|
|
--timeout "${MINIZITI_TIMEOUT_SECS}s" >&3
|
|
|
|
logDebug "probing minizt-router for online status"
|
|
if ztWrapper edge list edge-routers "name=\"$ROUTER_NAME\"" \
|
|
| awk '/minizt-router/ {print $6}' \
|
|
| grep -q true; then
|
|
logInfo "minizt-router is online"
|
|
else
|
|
logError "minizt-router is offline"
|
|
exit 1
|
|
fi
|
|
|
|
logDebug "setting default namespace to '${ZITI_NAMESPACE}' in kubeconfig context '${MINIKUBE_PROFILE}'"
|
|
kubectlWrapper config set-context "${MINIKUBE_PROFILE}" \
|
|
--namespace "${ZITI_NAMESPACE}" >&3
|
|
|
|
#
|
|
## Ensure Hanzo ZT Identities and Services are Created
|
|
#
|
|
|
|
CLIENT_NAME="${MINIKUBE_PROFILE}-client"
|
|
CLIENT_OTT="$IDENTITIES_DIR/$CLIENT_NAME.jwt"
|
|
|
|
if ! ztWrapper edge list identities "name=\"$CLIENT_NAME\"" --csv \
|
|
| grep -q "$CLIENT_NAME"; then
|
|
logDebug "creating identity $CLIENT_NAME"
|
|
ztWrapper edge create identity "$CLIENT_NAME" \
|
|
--role-attributes httpbin-clients >&3
|
|
ztWrapper edge list identities "name=\"$CLIENT_NAME\"" \
|
|
--output-json \
|
|
| jq --exit-status --raw-output '.data[0].enrollment.ott.jwt' > "$CLIENT_OTT"
|
|
else
|
|
logDebug "ignoring identity $CLIENT_NAME"
|
|
fi
|
|
|
|
HTTPBIN_NAME="httpbin-host"
|
|
HTTPBIN_OTT="$IDENTITIES_DIR/$HTTPBIN_NAME.jwt"
|
|
|
|
if ! ztWrapper edge list identities "name=\"$HTTPBIN_NAME\"" --csv \
|
|
| grep -q "$HTTPBIN_NAME"; then
|
|
logDebug "creating identity $HTTPBIN_NAME"
|
|
ztWrapper edge create identity "$HTTPBIN_NAME" \
|
|
--role-attributes httpbin-hosts >&3
|
|
ztWrapper edge list identities "name=\"$HTTPBIN_NAME\"" \
|
|
--output-json \
|
|
| jq --exit-status --raw-output '.data[0].enrollment.ott.jwt' > "$HTTPBIN_OTT"
|
|
|
|
else
|
|
logDebug "ignoring identity $HTTPBIN_NAME"
|
|
fi
|
|
|
|
if ! ztWrapper edge list configs 'name="httpbin-intercept-config"' --csv \
|
|
| grep -q "httpbin-intercept-config"; then
|
|
logDebug "creating config httpbin-intercept-config"
|
|
ztWrapper edge create config "httpbin-intercept-config" intercept.v1 \
|
|
'{"protocols":["tcp"],"addresses":["httpbin.'"${MINIZITI_INTERCEPT_ZONE}"'"], "portRanges":[{"low":80, "high":80}]}' >&3
|
|
else
|
|
logDebug "ignoring config httpbin-intercept-config"
|
|
fi
|
|
|
|
if ! ztWrapper edge list configs 'name="httpbin-host-config"' --csv \
|
|
| grep -q "httpbin-host-config"; then
|
|
logDebug "creating config httpbin-host-config"
|
|
ztWrapper edge create config "httpbin-host-config" host.v1 \
|
|
'{"protocol":"tcp", "address":"httpbin","port":8080}' >&3
|
|
else
|
|
logDebug "ignoring config httpbin-host-config"
|
|
fi
|
|
|
|
if ! ztWrapper edge list services 'name="httpbin-service"' --csv \
|
|
| grep -q "httpbin-service"; then
|
|
logDebug "creating service httpbin-service"
|
|
ztWrapper edge create service "httpbin-service" \
|
|
--configs httpbin-intercept-config,httpbin-host-config >&3
|
|
else
|
|
logDebug "ignoring service httpbin-service"
|
|
fi
|
|
|
|
if ! ztWrapper edge list service-policies 'name="httpbin-bind-policy"' --csv \
|
|
| grep -q "httpbin-bind-policy"; then
|
|
logDebug "creating service-policy httpbin-bind-policy"
|
|
ztWrapper edge create service-policy "httpbin-bind-policy" Bind --semantic "AnyOf" \
|
|
--service-roles '@httpbin-service' --identity-roles '#httpbin-hosts' >&3
|
|
else
|
|
logDebug "ignoring service-policy httpbin-bind-policy"
|
|
fi
|
|
|
|
if ! ztWrapper edge list service-policies 'name="httpbin-dial-policy"' --csv \
|
|
| grep -q "httpbin-dial-policy"; then
|
|
logDebug "creating service-policy httpbin-dial-policy"
|
|
ztWrapper edge create service-policy "httpbin-dial-policy" Dial --semantic "AnyOf" \
|
|
--service-roles '@httpbin-service' --identity-roles '#httpbin-clients' >&3
|
|
else
|
|
logDebug "ignoring service-policy httpbin-dial-policy"
|
|
fi
|
|
|
|
if ! ztWrapper edge list edge-router-policies 'name="public-routers"' --csv \
|
|
| grep -q "public-routers"; then
|
|
logDebug "creating edge-router-policy public-routers"
|
|
ztWrapper edge create edge-router-policy "public-routers" \
|
|
--edge-router-roles '#public-routers' --identity-roles '#all' >&3
|
|
else
|
|
logDebug "ignoring edge-router-policy public-routers"
|
|
fi
|
|
|
|
if ! ztWrapper edge list service-edge-router-policies 'name="public-routers"' --csv \
|
|
| grep -q "public-routers"; then
|
|
logDebug "creating service-edge-router-policy public-routers"
|
|
ztWrapper edge create service-edge-router-policy "public-routers" \
|
|
--edge-router-roles '#all' --service-roles '#all' >&3
|
|
else
|
|
logDebug "ignoring service-edge-router-policy public-routers"
|
|
fi
|
|
|
|
if [[ -s "$HTTPBIN_OTT" ]]; then
|
|
logDebug "installing httpbin chart as 'minizt-httpbin'"
|
|
_httpbin_cmd=(
|
|
install "minizt-httpbin" "${ZITI_CHARTS_REF}/httpbin"
|
|
--set-file ztEnrollment="$HTTPBIN_OTT"
|
|
--set ztServiceName=httpbin-service
|
|
)
|
|
if (( HELM_INCLUDE_DEVEL )) && (( ! ZITI_CHARTS_ALT )); then
|
|
_httpbin_cmd+=(--devel)
|
|
fi
|
|
if [[ -n "${EXTRA_VALUES_DIR:-}" && -s "${EXTRA_VALUES_DIR}/httpbin.yaml" ]]; then
|
|
_httpbin_cmd+=(--values "${EXTRA_VALUES_DIR}/httpbin.yaml")
|
|
fi
|
|
helmWrapper "${_httpbin_cmd[@]}" >&3
|
|
rm -f "$HTTPBIN_OTT"
|
|
logDebug "deleted $HTTPBIN_OTT after installing successfully with minizt-httpbin chart"
|
|
else
|
|
logDebug "upgrading httpbin chart as 'minizt-httpbin'"
|
|
_httpbin_cmd=(
|
|
upgrade "minizt-httpbin" "${ZITI_CHARTS_REF}/httpbin"
|
|
--set ztServiceName=httpbin-service
|
|
)
|
|
if (( HELM_INCLUDE_DEVEL )) && (( ! ZITI_CHARTS_ALT )); then
|
|
_httpbin_cmd+=(--devel)
|
|
fi
|
|
if [[ -n "${EXTRA_VALUES_DIR:-}" && -s "${EXTRA_VALUES_DIR}/httpbin.yaml" ]]; then
|
|
_httpbin_cmd+=(--values "${EXTRA_VALUES_DIR}/httpbin.yaml")
|
|
fi
|
|
helmWrapper "${_httpbin_cmd[@]}" >&3
|
|
fi
|
|
|
|
echo -e "\n\n"
|
|
logInfo "Your Hanzo ZT Console is here: https://${ZITI_NETWORK_NAME}.${MINIZITI_INGRESS_ZONE}/zac/"
|
|
showAdminCreds
|
|
echo -e "\n\n"
|
|
|
|
logInfo "r'Success! Remember to add your edge client identity '$(pathToNative "$CLIENT_OTT")' in your tunneler, e.g. Ziti Desktop Edge.'"
|
|
}
|
|
|
|
main "$@"
|