Use fzf for interactive selection of elements

This commit is contained in:
Daniel Berteaud 2023-08-14 23:55:31 +02:00
parent 039570d4ad
commit 2776831640
3 changed files with 77 additions and 105 deletions

View File

@ -3,17 +3,7 @@ _ctctl(){
_init_completion || return
case $prev in
auth|disconnect|prep|current|tokens|list|volumes|logs|conf)
return
;;
build|build-no-cache)
COMPREPLY=($(compgen -W "$(
(
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
) | perl -ne 'print "$1 " if /^oci\.ehtrace\.com\/([^:]+):.*/' | sort -u)
" -- $cur))
auth|disconnect|prep|current|tokens|list|build|build-no-cache|volumes|logs|conf)
return
;;
switch)

164
ctctl
View File

@ -6,10 +6,12 @@ current_env(){
echo "Unknown container domain"
kill -INT $$
fi
echo "${CTCTL_DOMAIN}"
echo "Cluster: ${CTCTL_DOMAIN}"
if [ -z "${CTCTL_ENV}" ]; then
echo "Unknown container environment"
kill -INT $$
fi
echo "Namespace: ${CTCTL_ENV}"
}
check_env() {
@ -57,23 +59,14 @@ load_config(){
# Switch to a target environment (either from no current, or from another current env)
switch_env(){
TARGET_DOM=$1
TARGET_ENV=$2
TARGET_NAMESPACE=$2
if [ -z "${TARGET_DOM}" ]; then
if [ $(ls_env | wc -w) -eq 1 ]; then
TARGET_DOM=$(ls_env)
else
echo "Select the container install you want to work on"
select T_DOM in $(ls_env); do
if [ "${REPLY}" -ge 1 ] && [ "${REPLY}" -le $(ls_env | wc -w) ]; then
TARGET_DOM=${T_DOM}
break
else
echo "Invalid selection"
fi
done
fi
elif [ ! -e ~/.ctctl/${TARGET_DOM}/ctctl.conf ]; 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
@ -90,26 +83,6 @@ switch_env(){
source ~/.ctctl/${CTCTL_DOMAIN}/ctctl.conf
set +o allexport
local ENV_LIST=$(echo -n ${CTCTL_VALID_ENV:-default} | sed 's/,/ /g')
if [ -z "${TARGET_ENV}" ]; then
if [ $(echo -n ${ENV_LIST} | wc -w) -eq 1 ]; then
TARGET_ENV=${ENV_LIST}
else
echo "Select the env you are working in"
local ENV_LIST=$(echo -n ${CTCTL_VALID_ENV:-default} | sed 's/,/ /g')
select T_ENV in ${ENV_LIST}; do
if [ "${REPLY}" -ge 1 ] && [ "${REPLY}" -le $(echo -n ${ENV_LIST} | wc -w) ]; then
TARGET_ENV=${T_ENV}
break
else
echo "Invalid selection, please select the env you'll be working in"
fi
done
fi
fi
export CTCTL_ENV=${TARGET_ENV}
# Load pre login env configuration
if [ -e ~/.ctctl/${CTCTL_DOMAIN}/pre-login.conf ]; then
set -o allexport
@ -117,30 +90,24 @@ switch_env(){
set +o allexport
fi
export NOMAD_VAR_env=${TARGET_ENV}
# Change color of the prompt
case ${CTCTL_ENV} in
prd|PRD|production)
COLOR="1;31" # Red
;;
stg|STG|stage|staging)
COLOR="1;33" # Yellow/Orange
;;
qa|qal|QA|QAL)
COLOR="1;35" # Purple
;;
dev|DEV|devel)
COLOR="1;36" # Cyan
;;
*)
COLOR="1;32" # Green
;;
esac
# Authenticate
auth_env
export PS1="[${CTCTL_DOMAIN} \[\e[${COLOR}m\](${CTCTL_ENV})\[\e[m\] \W]\$ "
local NAMESPACE_LIST=$(ls_namespace)
if [ -z "${TARGET_NAMESPACE}" ]; then
if [ $(echo -n ${NAMESPACE_LIST} | wc -w) -eq 1 ]; then
TARGET_NAMESPACE=${NAMESPACE_LIST}
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
@ -274,6 +241,18 @@ 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 "${DOCKER_BUILD_REPO_REGEX:-docker-repo.ehtrace.com}" | sort -u
}
# Load policies for vault, Consul and Nomad
load_policies(){
if [ "$(check_env)" = "0" ]; then
@ -373,38 +352,44 @@ load_consul_conf(){
fi
}
# Build Docker images
build_images(){
IMAGE=$1
FORCE=$2
NO_CACHE=$3
export DOCKER_BUILDKIT=1
for DOCKER_IMAGE in $(
(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 ${DOCKER_BUILD_REPO_REGEX:-docker-repo.ehtrace.com} | sort -u); do
if [ "${FORCE}" != "" ] || ! docker manifest inspect ${DOCKER_IMAGE} > /dev/null 2>&1; then
echo "Building image ${DOCKER_IMAGE}"
# Extract the basename of the image, removing the repo and the tag
DIR=$(echo -n ${DOCKER_IMAGE} | sed -E 's/.+\/([^\/]+):.*/\1/')
if [ "${IMAGE}" != "" -a "${DIR}" != "${IMAGE}" ]; then
echo "Skipping ${DIR}"
else
export DOCKER_IMAGE=${DOCKER_IMAGE}
LATEST=$(echo ${DOCKER_IMAGE} | sed 's/:.*/:latest/')
if [ "${NO_CACHE}" != "" ]; then
NO_CACHE="--no-cache"
else
NO_CACHE=""
fi
docker build ${NO_CACHE} -t ${DOCKER_IMAGE} -t ${LATEST} ${CTCTL_DOCKER_BUILD_OPTS:-} --progress=plain images/$DIR &&
docker push ${DOCKER_IMAGE}
docker push ${LATEST}
fi
# 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 DIR=$(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
docker build ${NO_CACHE} -t ${DOCKER_IMAGE} -t ${LATEST} ${CTCTL_DOCKER_BUILD_OPTS:-} --progress=plain images/$DIR &&
docker push ${DOCKER_IMAGE}
docker push ${LATEST}
unset DOCKER_BUILDKIT
}
@ -548,6 +533,7 @@ get_conf(){
get_merged_conf | yq ".$1"
}
FZF_CMD=${CTCTL_FZF_CMD:-fzf --height=~10% --cycle --bind 'space:toggle' --marker='*'}
# Return a space separated list of jobs the current dir
get_job_list(){
@ -578,7 +564,7 @@ case $1 in
load_policies
load_consul_services
load_consul_conf
build_images
build_required_images
renew_leases
;;
volumes)
@ -586,11 +572,11 @@ case $1 in
renew_leases
;;
build)
build_images "$2" "force"
build_selected_images
renew_leases
;;
build-no-cache)
build_images "$2" "force" "no-cache"
build_selected_images "no-cache"
renew_leases
;;
tokens)

View File

@ -3,14 +3,11 @@
BIN_DIR=~/bin
DEFAULT_USER=${CTCTL_USER:-$(whoami | sed -r 's/\@.*//')}
DEFAULT_DOMAIN=${CTCTL_DOMAIN:-consul}
DEFAULT_VALID_ENV=${CTCTL_VALID_ENV:-default}
read -p "Enter your user login [${DEFAULT_USER}] " INSTALL_USER
INSTALL_USER=${INSTALL_USER:-${DEFAULT_USER}}
read -p "Enter container domain [${DEFAULT_DOMAIN}] " INSTALL_DOMAIN
INSTALL_DOMAIN=${INSTALL_DOMAIN:-${DEFAULT_DOMAIN}}
read -p "Enter a command separated list of valid environments (poc,dev,stg,prd etc.) [${DEFAULT_VALID_ENV}] " INSTALL_VALID_ENV
INSTALL_VALID_ENV=${INSTALL_VALID_ENV:-${DEFAULT_VALID_ENV}}
function get_gh_release() {
local VERSION
@ -41,7 +38,7 @@ if [ "${MACHINE}" = "unknown" ]; then
fi
# Check that we have the required utilities
for TOOL in jq openssl curl unzip; do
for TOOL in jq openssl curl unzip fzf; do
if ! command -v $TOOL > /dev/null 2>&1; then
echo "$TOOL not found. Please install it first"
exit 1
@ -135,7 +132,6 @@ cp -f ctctl.example.conf ~/.ctctl/${INSTALL_DOMAIN}/ctctl.example.conf
cat <<_EOF > ~/.ctctl/${INSTALL_DOMAIN}/ctctl.conf
CTCTL_USER=${INSTALL_USER}
CTCTL_DOMAIN=${INSTALL_DOMAIN}
CTCTL_VALID_ENV=${INSTALL_VALID_ENV}
_EOF
cat << '_EOF' > ~/.local/share/bash-completion/completions/vault
complete -C ~/bin/vault vault