This repository has been archived on 2020-01-20. You can view files and clone it, but cannot push or open issues or pull requests.
node-spearhead/etc/triton-bash-completion-types.sh

183 lines
5.9 KiB
Bash
Raw Permalink Normal View History

# Functions for Bash completion of some 'triton' option/arg types.
function complete_tritonprofile {
local word="$1"
local candidates
candidates=$(ls -1 ~/.triton/profiles.d/*.json 2>/dev/null \
| sed -E 's/^.*\/([^\/]+)\.json$/\1/')
compgen $compgen_opts -W "$candidates" -- "$word"
}
#
# Get completions for a given type of Triton (server-side) data.
#
# Usage:
# _complete_tritondata $type # e.g. _complete_tritondata images
#
# The easiest/slowest thing to do to complete images would be to just call:
# triton [profile-related-args] images -Ho name
# or similar. Too slow.
#
# The next easiest would be this:
# candidates=$(TRITON_COMPLETE=$type $COMP_LINE)
# where `triton` is setup to specially just handle completions if
# `TRITON_COMPLETE` is set. That special handling writes out a cache file to
# avoid hitting the server every time. This is still too slow because the
# node.js startup time for `triton` is too slow (around 1s on my laptop).
#
# The next choice is to (a) use the special `TRITON_COMPLETE` handling to
# fetch data from the server and write out a cache file, but (b) attempt to
# find and use that cache file without calling node.js code. The win is
# (at least in my usage) faster response time to a <TAB>. The cost is
# reproducing (imperfectly) in Bash the logic for determining the Triton profile
# info to find the cache.
#
function _complete_tritondata {
local type=$1
# First, find the Triton CLI profile.
local profile
profile=$(echo "$COMP_LINE" | grep -- '\s\+-p\s*\w\+\s\+' | sed -E 's/.* +-p *([^ ]+) +.*/\1/')
if [[ -z "$profile" ]]; then
profile=$TRITON_PROFILE
fi
if [[ -z "$profile" ]]; then
profile=$(grep '"profile":' ~/.triton/config.json | cut -d'"' -f4)
fi
if [[ -z "$profile" ]]; then
profile=env
fi
trace " profile: $profile"
# Then, determine the account and url that go into the cache dir.
# TODO: include -a/-U options that change from profile values
# TODO: subuser support
local url
local account
local profileFile
profileFile=$HOME/.triton/profiles.d/$profile.json
if [[ "$profile" == "env" ]]; then
url=$TRITON_URL
if [[ -z "$url" ]]; then
url=$SDC_URL
fi
account=$TRITON_ACCOUNT
if [[ -z "$account" ]]; then
account=$SDC_ACCOUNT
fi
elif [[ -f $profileFile ]]; then
url=$(grep '"url":' $profileFile | cut -d'"' -f4)
account=$(grep '"account":' $profileFile | cut -d'"' -f4)
fi
trace " url: $url"
trace " account: $account"
# Mimic node-triton/lib/common.js#profileSlug
local profileSlug
profileSlug="$(echo "$account" | sed -E 's/@/_/g')@$(echo "$url" | sed -E 's#^https?://##')"
profileSlug="$(echo "$profileSlug" | sed -E 's/[^a-zA-Z0-9_@-]/_/g')"
local cacheFile
cacheFile="$HOME/.triton/cache/$profileSlug/$type.completions"
trace " cacheFile: $cacheFile"
# If we have a cache file, remove it and regenerate if it is >5 minutes old.
#
# Dev Note: This 5min TTL should match what `lib/cli.js#_emitCompletions()`
# is using.
local candidates
if [[ ! -f "$cacheFile" ]]; then
candidates=$(TRITON_COMPLETE=$type $COMP_LINE)
else
local mtime
mtime=$(stat -r "$cacheFile" | awk '{print $10}')
local ttl=300 # 5 minutes in seconds
local age
age=$(echo "$(date +%s) - $mtime" | bc)
if [[ $age -gt $ttl ]]; then
# Out of date. Regenerate the cache file.
trace " cacheFile out-of-date (mtime=$mtime, age=$age, ttl=$ttl)"
rm "$cacheFile"
candidates=$(TRITON_COMPLETE=$type $COMP_LINE)
else
trace " cacheFile is in-date (mtime=$mtime, age=$age, ttl=$ttl)"
candidates=$(cat "$cacheFile")
fi
fi
echo "$candidates"
}
function complete_tritonpackage {
local word="$1"
candidates=$(_complete_tritondata packages)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonimage {
local word="$1"
candidates=$(_complete_tritondata images)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritoninstance {
local word="$1"
candidates=$(_complete_tritondata instances)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonnetwork {
local word="$1"
candidates=$(_complete_tritondata networks)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonfwrule {
local word="$1"
candidates=$(_complete_tritondata fwrules)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonkey {
local word="$1"
candidates=$(_complete_tritondata keys)
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonaffinityrule {
local word="$1"
candidates=$(_complete_tritondata affinityrules)
# Triton affinity rules typically have '=' in them, e.g.:
# triton create -a inst==db0 ...
# This means we run afoul of the '=' in COMP_WORDBREAKS which results in
# triton create -a inst=<TAB>
# leading to:
# triton create -a inst=inst==
# The answer is to strip off at the last '=' in the returned completions.
if [[ "$word" == *"="* ]]; then
local uptolastequal
uptolastequal="${word%=*}="
compgen $compgen_opts -W "$candidates" -- "$word" \
| cut -c$(( ${#uptolastequal} + 1 ))-
else
compgen $compgen_opts -W "$candidates" -- "$word"
fi
}
function complete_tritonupdateaccountfield {
local word="$1"
local candidates
candidates="{{UPDATE_ACCOUNT_FIELDS}}"
compgen $compgen_opts -W "$candidates" -- "$word"
}
function complete_tritonupdatefwrulefield {
local word="$1"
local candidates
candidates="{{UPDATE_FWRULE_FIELDS}}"
compgen $compgen_opts -W "$candidates" -- "$word"
}