ctctl/ctctl

732 lines
23 KiB
Bash
Executable File

#!/usr/bin/env bash
# Print current environnement
current_env(){
if [ -z "${CTCTL_DOMAIN}" ]; then
echo "Unknown container domain"
kill -INT $$
fi
echo "Cluster: ${CTCTL_DOMAIN}"
if [ -z "${CTCTL_ENV}" ]; then
echo "Unknown container environment"
kill -INT $$
fi
echo "Namespace: ${CTCTL_ENV}"
}
check_env() {
if [ -n "${CTCTL_DOMAIN}" -a -n "${CTCTL_ENV}" ]; then
echo 1
else
echo 0
fi
}
# Run a shell in a container
# TODO : to implement
enter_ct(){
echo "Select the job"
select J in $(get_job_list); do
if [ "${REPLY}" -ge 1 ] && [ "${REPLY}" -le $(get_job_list | wc -w) ]; then
JOB=${J}
break
else
echo "Invalid selection"
fi
done
}
load_config(){
if [ -n "${CTCTL_DOMAIN}" -a -n "${CTCTL_ENV}" ]; then
# Load env configuration
if [ -e ~/.ctctl/${TARGET_DOM}/${CTCTL_ENV}.conf ]; then
set -o allexport
source ~/.ctctl/${TARGET_DOM}/${CTCTL_ENV}.conf
set +o allexport
fi
# Load post login configuration
if [ -e ~/.ctctl/${CTCTL_DOMAIN}/ctctl.local.conf ]; then
set -o allexport
source ~/.ctctl/${CTCTL_DOMAIN}/ctctl.local.conf
set +o allexport
fi
fi
}
# Switch to a target environment (either from no current, or from another current env)
switch_env(){
TARGET_DOM=$1
TARGET_NAMESPACE=$2
if [ -z "${TARGET_DOM}" ]; then
echo "Select the container install you want to work on"
TARGET_DOM=$(ls_env | ${FZF_CMD})
fi
if [ ! -e ~/.ctctl/${TARGET_DOM}/ctctl.conf ]; then
echo "Env ${TARGET_DOM} doesn't exist"
kill -INT $$
fi
# Clear any variable
for VAR in $(printenv | grep -E '^(CTCTL|CONSUL|VAULT|NOMAD)_.*' | sed -E 's/^([^=]+)=.*/\1/'); do
unset ${VAR}
done
export CTCTL_DOMAIN=${TARGET_DOM}
# Load default config
set -o allexport
source ~/.ctctl/${CTCTL_DOMAIN}/ctctl.conf
set +o allexport
# Load pre login env configuration
if [ -e ~/.ctctl/${CTCTL_DOMAIN}/pre-login.conf ]; then
set -o allexport
source ~/.ctctl/${CTCTL_DOMAIN}/pre-login.conf
set +o allexport
fi
# Authenticate
auth_env
if [ -z "${TARGET_NAMESPACE}" ]; then
if [ $(ls_namespace | wc -w) -eq 1 ]; then
TARGET_NAMESPACE=$(ls_namespace)
else
echo "Select the namespace you are working in"
TARGET_NAMESPACE=$(ls_namespace | ${FZF_CMD})
fi
fi
export CTCTL_ENV=${TARGET_NAMESPACE}
# TODO : decide if we keep NOMAD_VAR_env
export NOMAD_VAR_env=${TARGET_NAMESPACE}
export NOMAD_NAMESPACE=${TARGET_NAMESPACE}
}
# Check if we have a valid token for vault
check_vault_token(){
vault token lookup > /dev/null 2>&1
if vault token lookup > /dev/null 2>&1; then
echo 1
elif [ -n "${VAULT_TOKEN:-}" -a -e ~/.vault-token ]; then
# If VAULT_TOKEN is defined, unset it and try again. This is because we might
# have a valid token in ~/.vault-token but an expired token is set in VAULT_TOKEN
# and is taking precedence
export VAULT_TOKEN=$(cat ~/.vault-token)
if vault token lookup > /dev/null 2>&1; then
echo 1
else
echo 0
fi
else
echo 0
fi
}
# Check if we have a valid token for consul
check_consul_token(){
CONSUL_TOKEN_VALID=0
if [ -n "${CONSUL_HTTP_TOKEN}" ]; then
consul acl token read -self > /dev/null 2>&1
if [ $? == 0 ]; then
echo 1
else
echo 0
fi
else
echo 0
fi
}
# Check if we have a valid token for nomad
check_nomad_token(){
if [ -n "${NOMAD_TOKEN}" ]; then
nomad acl token self > /dev/null 2>&1
if [ $? == 0 ]; then
echo 1
else
echo 0
fi
else
echo 0
fi
}
# Auth on vault, consul and nomad on the current env
auth_env(){
if [ -z "${CTCTL_DOMAIN}" ]; then
echo "Unknown environment"
kill -INT $$
fi
if [ "$(check_vault_token)" != "1" ]; then
echo "You're not connected on vault. Please enter your account password"
export VAULT_TOKEN=$(vault login -field=token ${VAULT_AUTH_CONFIG:--method=ldap username=${CTCTL_USER:-$(whoami | sed -r 's/\@.*//')}} || kill -INT $$)
echo "Logged on vault successfuly"
else
echo "Your vault token is valid"
vault token renew > /dev/null 2>&1
fi
VAULT_TOKEN_INFO=$(vault token lookup -format=json)
# TODO make the role selection more generic
if [ "$(echo $VAULT_TOKEN_INFO | jq '.data.policies | any(. == "admin-policy" or .== "admin")')" == "true" ]; then
NOMAD_ROLE=admin
CONSUL_ROLE=admin
else
NOMAD_ROLE=user
CONSUL_ROLE=user
fi
# Root CA
vault read -field certificate pki/root/cert/ca > ~/.ctctl/${CTCTL_DOMAIN}/root_ca.crt
# Consul certificate
# Get/renew cert if required.
# Note 1: as the template is using pkiCert, the cert won't be renewed, unless necessary
# Note 2: don't pass CONSUL_CLIENT_CERT CONSUL_CLIENT_KEY and CONSUL_CACERT because they would prevent consul-template from starting
# to get/renew the cert if they are absent, or expired
env -u CONSUL_CLIENT_CERT \
-u CONSUL_CLIENT_KEY \
-u CONSUL_CACERT \
consul-template -config ~/.ctctl/${CTCTL_DOMAIN}/consul/consul-template.hcl -once
# Get/renew cert for Nomad now
consul-template -config ~/.ctctl/${CTCTL_DOMAIN}/nomad/consul-template.hcl -once
# Check if we have a valid nomad token already
if [ "$(check_nomad_token)" != "1" ]; then
echo "Fecthing a Nomad token from vault"
NOMAD_CREDS=$(vault read -format=json ${VAULT_PREFIX:-}nomad/creds/${NOMAD_ROLE})
export NOMAD_TOKEN=$(echo -n ${NOMAD_CREDS} | jq -r .data.secret_id)
export NOMAD_LEASE=$(echo -n ${NOMAD_CREDS} | jq -r .lease_id)
unset NOMAD_CREDS
else
echo "Nomad token is valid, renewing lease"
vault lease renew ${NOMAD_LEASE} >/dev/null
fi
# Check if we have a valid consul token already
if [ "$(check_consul_token)" != "1" ]; then
echo "Fetching a Consul token from vault"
CONSUL_CREDS=$(vault read -format=json ${VAULT_PREFIX:-}consul/creds/${CONSUL_ROLE})
export CONSUL_HTTP_TOKEN=$(echo -n ${CONSUL_CREDS} | jq -r .data.token)
export CONSUL_LEASE=$(echo -n ${CONSUL_CREDS} | jq -r .lease_id)
unset CONSUL_CREDS
else
echo "Consul token is valid, renewing lease"
vault lease renew ${CONSUL_LEASE} >/dev/null
fi
load_config
}
renew_leases(){
# Renew vault token
[ -n "${VAULT_TOKEN}" ] && vault token renew >/dev/null
[ -n "${NOMAD_LEASE}" ] && vault lease renew ${NOMAD_LEASE} >/dev/null
[ -n "${CONSUL_LEASE}" ] && vault lease renew ${CONSUL_LEASE} > /dev/null
}
# Logout from the current env
logout_env(){
if [ -z "${CTCTL_DOMAIN}" ]; then
echo "Unknown environment"
kill -INT $$
fi
echo "Disconecting from ${CTCTL_DOMAIN} environment"
vault token revoke -self
for VAR in $(printenv | perl -ne '/^((CTCTL|CONSUL|VAULT|NOMAD|LOKI)_[^=]+)=.*/ && print "$1\n"'); do
unset $VAR
done
rm -f ~/.vault-token
}
# List available env
ls_env(){
find ~/.ctctl/ -name ctctl.conf | xargs dirname | xargs basename -a
}
# List available namespaces
ls_namespace(){
nomad namespace list -json | jq -r ".[] | .Name"
}
# List buildable Docker images
ls_build_docker_images(){
(for JOB in $(find . -maxdepth 1 \( -name \*.nomad -o -name \*.nomad.hcl \)); do
nomad run -output $JOB | jq '.Job.TaskGroups' | jq '.[] | .Tasks' | jq -r '.[] | .Config.image' 2>/dev/null
done) | grep -E "${CTCTL_DOCKER_BUILD_REPO_REGEX:-docker-repo.ehtrace.com}" | sort -u
}
# Load policies for vault, Consul and Nomad
load_policies(){
if [ "$(check_env)" = "0" ]; then
echo "Not currently in a valid env. Run ctctl (with no argument) and select your env first"
kill -INT $$
fi
for DIR in ./output ./; do
if [ -d "${DIR}/vault/policies" ]; then
if [ "$(check_vault_token)" != "1" ]; then
echo "No valid vault token. You have to authenticate first"
kill -INT $$
fi
for PFILE in $(ls ${DIR}/vault/policies/*.hcl 2>/dev/null); do
PNAME=$(basename ${PFILE} .hcl)
echo "Loading vault policy ${PNA}"
replace_conf_var ${PFILE} | vault policy write ${PNAME} -
done
fi
if [ -d "${DIR}/consul/policies" ]; then
if [ "$(check_consul_token)" != "1" ]; then
echo "No valid consul token. You have to authenticate first"
kill -INT $$
fi
CONSUL_CUR_POLICIES=$(consul acl policy list -format=json)
for PFILE in $(ls ${DIR}/consul/policies/*.hcl 2>/dev/null); do
PNAME=$(basename ${PFILE} .hcl)
# Consul do not use the same command to create a new policy and to update an existing one
# so we need to detect if the policy already exists
if [ "$(echo ${CONSUL_CUR_POLICIES} | jq -r '.[] | select(.Name=='\"${PNAME}\"') | .Name')" == "${PNAME}" ]; then
echo "Updating consul policy ${PNAME}"
replace_conf_var ${PFILE} | consul acl policy update -name=${PNAME} -rules=-
else
echo "Adding new consul policy ${PNAME}"
replace_conf_var ${PFILE} | consul acl policy create -name=${PNAME} -rules=-
fi
done
fi
if [ -d "${DIR}/nomad/policies" ]; then
if [ "$(check_nomad_token)" != "1" ]; then
echo "No valid nomad token. You have to authenticate first"
kill -INT $$
fi
for PFILE in $(ls ${DIR}nomad/policies/*.hcl 2>/dev/null); do
PNAME=$(basename ${PFILE} .hcl)
echo "Loading Nomad policy ${PNAME}"
replace_conf_var ${PFILE} | nomad acl policy apply ${PNAME} -
done
fi
done
}
# Load consul config
load_consul_conf(){
for DIR in ./output ./; do
if [ -d "${DIR}/consul/config" ]; then
if [ "$(check_consul_token)" != "1" ]; then
echo "No valid consul token. You have to authenticate first"
kill -INT $$
fi
# Note : service-defaults should be loaded before the others
# but that should be the case
for FILE in $(ls ${DIR}/consul/config/*.hcl 2>/dev/null); do
echo "Loading consul conf from ${FILE}"
TEMP=$(mktemp)
replace_conf_var ${FILE} > ${TEMP}
consul config write ${TEMP}
rm -f ${TEMP}
done
# Support storing consul config in subdir eg consul/config/service-defaults/foo.hcl
# Or you can even omit service and use consul/config/defaults/bar.hcl, consul/config/intentions/bar.hcl
for KIND in service-defaults service-intentions service-router service-resolver proxy-defaults; do
if [ -d ${DIR}/consul/config/${KIND} ]; then
for FILE in $(ls ${DIR}/consul/config/${KIND}/*.hcl 2>/dev/null); do
echo "Loading consul conf from ${FILE}"
TEMP=$(mktemp)
replace_conf_var ${FILE} > ${TEMP}
consul config write ${TEMP}
rm -f ${TEMP}
done
fi
done
fi
done
}
# Build all images for the current project
build_required_images(){
for DOCKER_IMAGE in $(ls_build_docker_images); do
if ! docker manifest inspect ${DOCKER_IMAGE} > /dev/null 2>&1; then
build_image ${DOCKER_IMAGE}
else
echo "Image ${DOCKER_IMAGE} already available"
fi
done
}
# Build selected images
build_selected_images(){
local NO_CACHE=$1
for DOCKER_IMAGE in $(ls_build_docker_images | ${FZF_CMD} -m); do
build_image "${DOCKER_IMAGE}" ${NO_CACHE}
done
}
# Build a single image
build_image(){
local DOCKER_IMAGE=$1
local NO_CACHE=$2
export DOCKER_BUILDKIT=1
echo "Building image ${DOCKER_IMAGE}"
# Extract the basename of the image, removing the repo and the tag
local IMAGE_NAME=$(echo -n ${DOCKER_IMAGE} | sed -E 's/.+\/([^\/]+):.*/\1/')
export DOCKER_IMAGE=${DOCKER_IMAGE}
local LATEST=$(echo ${DOCKER_IMAGE} | sed 's/:.*/:latest/')
if [ "${NO_CACHE}" != "" ]; then
NO_CACHE="--no-cache"
else
NO_CACHE=""
fi
local FOUND=0
for DIR in ./images ./output/images; do
if [ -d $DIR/${IMAGE_NAME} ]; then
docker build ${NO_CACHE} -t ${DOCKER_IMAGE} ${CTCTL_DOCKER_BUILD_OPTS:-} --progress=plain $DIR/${IMAGE_NAME} &&\
docker push ${DOCKER_IMAGE} &&\
docker push ${LATEST}
FOUND=1
break
fi
done
if [ "${FOUND}" = "0" ]; then
echo "Couldn't find Docker image directory"
kill -INT $$
fi
unset DOCKER_BUILDKIT
}
# Run all executable in the prep.d directory
handle_prep_scripts(){
for DIR in ./output ./; do
if [ -d "${DIR}/prep.d" ]; then
for H in $(find ${DIR}/prep.d -type f -o -type l | sort); do
if [ -x "${H}" ]; then
echo "Running prep script ${H}"
$H $1
else
echo "Skiping prep script $H (not executable)"
fi
done
fi
done
}
# Update ctctl bundles with git
update_submodules(){
if [ -e ctctl.bundle.conf ]; then
set -o allexport
source ./ctctl.bundle.conf
set +o allexport
for ID in $(printenv | grep -P '^CTCTL_BUNDLE_\d+_NAME=' | sed -E 's/CTCTL_BUNDLE_([0-9]+)_NAME.*/\1/'); do
local NAME=$(printenv CTCTL_BUNDLE_${ID}_NAME)
local URL=$(printenv CTCTL_BUNDLE_${ID}_URL)
local BRANCH=$(printenv CTCTL_BUNDLE_${ID}_BRANCH || echo master)
echo "Working on the ${NAME} bundle"
if [ ! -d bundles/${NAME} ]; then
echo "Adding sub module from ${URL} (branch ${BRANCH})"
git submodule add --branch ${BRANCH} --name ${NAME} --force ${URL} bundles/${NAME}
else
echo "Updating ${NAME} from ${URL} (branch ${BRANCH})"
git submodule set-branch --branch ${BRANCH} bundles/${NAME}
fi
git submodule update --init --recursive --remote --merge bundles/${NAME}
done
fi
}
# Render templates using gomplate (or levant for backward compat)
render_templates(){
# If a ctctl.bundle.conf file exist, use the new gomplate rendering method
if [ -e ctctl.bundle.conf ]; then
set -o allexport
source ./ctctl.bundle.conf
set +o allexport
mkdir -p bundles
for ID in $(printenv | grep -P '^CTCTL_BUNDLE_\d+_NAME=' | sed -E 's/CTCTL_BUNDLE_([0-9]+)_NAME.*/\1/'); do
local NAME=$(printenv CTCTL_BUNDLE_${ID}_NAME)
local URL=$(printenv CTCTL_BUNDLE_${ID}_URL)
local BRANCH=$(printenv CTCTL_BUNDLE_${ID}_BRANCH || echo master)
echo "Working on the ${NAME} bundle"
if [ ! -d bundles/${NAME} ]; then
update_submodules
fi
# Use [[ and ]] so it won't clash with consul-template fragments
local GOMPLATE_COMMON_ARGS=(--left-delim '[[' --right-delim ']]')
# The context will merge various configuration files to get the variables used to render the templates
GOMPLATE_COMMON_ARGS+=(--context)
# Build a list of configuration file to merge
# Files are in order of precedence (firsts win)
I=0
local VAR_FILES=""
for FILE in ${NOMAD_NAMESPACE}.yml \
${NOMAD_NAMESPACE}.yaml \
variables.yml \
variables.yaml \
../${NOMAD_NAMESPACE}.yml \
../${NOMAD_NAMESPACE}.yaml \
../variables.yml \
../variables.yaml \
bundles/${NAME}/variables.yml \
bundles/${NAME}/variables.yaml \
bundles/${NAME}/deps/*/variables.yml \
bundles/${NAME}/deps/*/variables.yaml; do
if [ -e ${FILE} ]; then
if [ $I -eq 0 ]; then
VAR_FILES+='.=merge:'
else
VAR_FILES+='|'
fi
VAR_FILES+="${FILE}"
I=$((I+1))
fi
done
GOMPLATE_COMMON_ARGS+=("${VAR_FILES}")
for TEMPLATE_DIR in $(find bundles -type d -name templates); do
GOMPLATE_COMMON_ARGS+=(--template "$(basename $(dirname ${TEMPLATE_DIR}))=${TEMPLATE_DIR}")
# Also declare sub-folders as external templates
for SUBFOLDER in $(find ${TEMPLATE_DIR} -mindepth 1 -maxdepth 2 -type d); do
GOMPLATE_COMMON_ARGS+=(--template "$(basename $(dirname ${TEMPLATE_DIR}))/$(basename ${SUBFOLDER})=${SUBFOLDER}")
done
done
local GOMPLATE_BUNDLE_ARGS=(--input-dir "bundles/${NAME}")
# Do not render templates from dependencies, variables files and images (images will be handled later)
GOMPLATE_BUNDLE_ARGS+=(--exclude .git* --exclude deps/** --exclude variables.yml --exclude images/** --exclude templates/**)
# This is used for two things
# - Add the env.suffix to every files (except job files). This permit ctctl to simply infer the policy name from the file name
# - Put job files in the current dir for conveniance, and everything else in the output dir
GOMPLATE_BUNDLE_ARGS+=(--output-map)
GOMPLATE_BUNDLE_ARGS+=('[[ if (regexp.Match ".*\\.nomad(\\.hcl)?" .in) ]][[ .in ]][[ else ]]output/[[ .in | path.Dir ]]/[[ .in | path.Base | regexp.Replace "^([^\\.]+)\\.(.*)$" (printf "%s%s.%s" "$1" .ctx.env.suffix "$2") ]][[ end ]]')
echo
echo "Redering bundles with gomplate ${GOMPLATE_COMMON_ARGS[@]} ${GOMPLATE_BUNDLE_ARGS[@]}"
# First, cleanup any previously rendered files
rm -rf output ./*.nomad ./*.nomad.hcl
gomplate "${GOMPLATE_COMMON_ARGS[@]}" "${GOMPLATE_BUNDLE_ARGS[@]}"
for IMGDIR in $(find . -name images -type d); do
for DOCKER_IMAGE in $(find ${IMGDIR} -mindepth 1 -maxdepth 1 -type d); do
echo "Redering Docker image $(basename ${DOCKER_IMAGE})"
gomplate "${GOMPLATE_COMMON_ARGS[@]}" --input-dir ${DOCKER_IMAGE} --exclude resources/** --exclude root/** --output-dir output/images/$(basename ${DOCKER_IMAGE})/
for ROOT in resources root; do
if [ -d "${DOCKER_IMAGE}/${ROOT}" ]; then
cp -r "${DOCKER_IMAGE}/${ROOT}" output/images/$(basename ${DOCKER_IMAGE})/
fi
done
done
done
echo
echo "Formating job files"
find ./ -maxdepth 1 -type f \( -name \*nomad.hcl -o -name \*.nomad \) -exec nomad fmt {} \;
# Run prep.d scripts
handle_prep_scripts
done
# Cleanup variables
for VAR in $(printenv | grep -E '^CTCTL_BUNDLE_.*' | sed -E 's/^([^=]+)=.*/\1/'); do
unset ${VAR}
done
else
# backward compatible, levant based rendering
MERGED_CONF=$(mktemp tmp.XXXXXXXX.yml)
get_merged_conf > ${MERGED_CONF}
# TODO : handle prep scripts with the new bundles system
handle_prep_scripts ${MERGED_CONF}
for TEMPLATE in $(find . -type f -name \*.tpl ! -path "*templates/*"); do
local DIR=$(dirname ${TEMPLATE})
local FILE=$(basename ${TEMPLATE} .tpl)
local DEST=${DIR}/${FILE}
echo "Rendering ${TEMPLATE} into ${DEST}"
# Note: render twice, so included templates get rendered too
levant render -var-file ${MERGED_CONF} -log-level=WARN <(levant render -var-file ${MERGED_CONF} -log-level=WARN ${TEMPLATE}) > ${DEST}
nomad fmt ${DEST}
done
rm -f ${MERGED_CONF}
fi
}
# Print Consul and Nomad tokens (not vault, for security reasons)
print_tokens(){
if [ "$(check_nomad_token)" == "1" ]; then
echo "Nomad token: ${NOMAD_TOKEN}"
else
echo "No valid Nomad token, you should auth with ctctl auth"
fi
if [ "$(check_consul_token)" == "1" ]; then
echo "Consul token: ${CONSUL_HTTP_TOKEN}"
else
echo "No valid Consul token, you should auth with ctctl auth"
fi
}
# Follow current jobs logs
job_logs(){
# Remove the first arg passed to ctctl, which is logs
shift
local SELECTOR
local LOGCLI_CMD
if [ -z "${LOKI_ADDR}" ]; then
echo "You need to configure loki first (LOKI_ADDR, LOKI_USERNAME and LOKI_PASSWORD or LOKI_PWD_CMD)"
kill -INT $$
fi
if [ -n "${LOKI_PWD_CMD}" ]; then
export LOKI_PASSWORD=$(${LOKI_PWD_CMD})
fi
LOGCLI_CMD="logcli query --include-label=job --include-label=group --include-label=task"
echo -n "$*" | grep -qP '\{.+\}' >/dev/null 2>&1
# If a logcli filter was given, use it. Else, build one for jobs in the current dir
if [ $? == 0 ]; then
echo "Running ${LOGCLI_CMD} $@"
${LOGCLI_CMD} $@
else
# Exclude connect-proxy logs as it's often not wanted
SELECTOR='{job=~"'$(get_job_list | sed 's/\s/|/g')'", task!~"connect-proxy-.+|tls-proxy|metrics-proxy"}'
echo "Running ${LOGCLI_CMD} $@ ${SELECTOR}"
${LOGCLI_CMD} $@ "${SELECTOR}"
fi
unset LOKI_PASSWORD
}
### Helpers ###
# Merge the configuration files for the current env and return the result (as string)
get_merged_conf() {
CONF_FILES=""
if [ -e "./vars/defaults.yml" ]; then
CONF_FILES="./vars/defaults.yml"
fi
if [ -e "jobs/common/vars/${CTCTL_ENV}.yml" ]; then
CONF_FILES="${CONF_FILES} jobs/common/vars/${CTCTL_ENV}.yml"
fi
if [ -e "../common/vars/${CTCTL_ENV}.yml" ]; then
CONF_FILES="${CONF_FILES} ../common/vars/${CTCTL_ENV}.yml"
fi
if [ -e "./vars/${CTCTL_ENV}.yml" ]; then
CONF_FILES="${CONF_FILES} ./vars/${CTCTL_ENV}.yml"
fi
if [ "${CONF_FILES}" != "" ]; then
echo "---"
yq ea '. as $item ireduce ({}; . * $item | ... comments="")' $CONF_FILES
else
echo -n ""
fi
}
# Replace ${local.conf.foo} or ${foo} with the value of foo from the various merged configuration files
# This is used to have policies (vault, consul, nomad) and config (consul intentions etc.) with variables
replace_conf_var() {
MERGED_CONF=$(mktemp)
get_merged_conf > $MERGED_CONF
RES=$(cat $1 | \
# Replace ${local.conf.foo} or ${foo} with the value of foo from the various merged configuration files \
# This is used to have policies (vault, consul, nomad) and config (consul intentions etc.) with variables \
perl -pe 'sub replace($) { my $val = shift; chomp(my $res = qx(yq .$val '$MERGED_CONF')); return $res; }; s!\$\{(local\.conf\.)?([^\}]+)\}! replace($2) !ge' | \
# Replace $(foo) with the output of foo command, mainly used to fetch secrets from vault \
perl -pe 'sub replace($) { my $val = shift; chomp(my $res = qx($val)); return $res; }; s!\$\(([^\)]+)\)! replace($1) !ge'
)
rm -f $MERGED_CONF
echo "${RES}"
}
# Get a value from the conf
get_conf(){
get_merged_conf | yq ".$1"
}
# Return a space separated list of jobs the current dir
get_job_list(){
local JOBS=""
for JOBFILE in $(find . -maxdepth 1 \( -name \*.nomad -o -name \*.nomad.hcl \)); do
JOBS="${JOBS} $(nomad run -output ${JOBFILE} | jq -r '.Job.Name')"
done
echo $JOBS
}
FZF_CMD=${CTCTL_FZF_CMD:-fzf --height=~10% --cycle --bind 'space:toggle' --marker='*'}
case $1 in
current)
current_env
renew_leases
;;
auth)
auth_env
;;
disconnect)
logout_env
;;
ls|list)
ls_env
renew_leases
;;
render)
render_templates
renew_leases
;;
prep)
update_submodules
render_templates
load_policies
load_consul_conf
build_required_images
renew_leases
;;
build)
build_selected_images
renew_leases
;;
build-no-cache)
build_selected_images "no-cache"
renew_leases
;;
tokens)
print_tokens
renew_leases
;;
logs)
renew_leases
job_logs "$@"
;;
conf)
renew_leases
get_merged_conf
;;
sh)
enter_ct
;;
switch)
shift
switch_env "$@"
;;
*)
switch_env "$@"
;;
esac