From 2776831640633cf4103fe3dcd2f6c1b55f479ac0 Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Mon, 14 Aug 2023 23:55:31 +0200 Subject: [PATCH] Use fzf for interactive selection of elements --- bash_completion | 12 +--- ctctl | 164 ++++++++++++++++++++++-------------------------- install.sh | 6 +- 3 files changed, 77 insertions(+), 105 deletions(-) diff --git a/bash_completion b/bash_completion index 98ce1cc..66684ef 100644 --- a/bash_completion +++ b/bash_completion @@ -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) diff --git a/ctctl b/ctctl index 20cc128..a2b02b2 100755 --- a/ctctl +++ b/ctctl @@ -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) diff --git a/install.sh b/install.sh index e31e998..4827801 100755 --- a/install.sh +++ b/install.sh @@ -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