=====================================================================

--- Changes ------------------------------

- kubectl driver updates; getting better, but still need to fix
  autocomplete in certain circumstances

- added -y|--yes flags to scwrypts to auto-accept user-prompts (use with
  caution)

- figured out the whole mikefarah/yq vs kislyuk/yq thing; use YQ for
  compatiblity

--- Bug fixes ----------------------------

- helm template generation now loads values in a more appropriate order
  which prevents overwrite by the wrong values file
This commit is contained in:
2023-11-22 15:54:16 -07:00
parent a03885e8db
commit 72e831da33
14 changed files with 354 additions and 37 deletions

View File

@ -7,4 +7,4 @@ use cloud/aws/eks
CHECK_ENVIRONMENT
#####################################################################
EKS_CLUSTER_LOGIN $@
EKS__CLUSTER_LOGIN $@

View File

@ -1,19 +1,44 @@
#####################################################################
DEPENDENCIES+=(
kubectl
)
REQUIRED_ENV+=(
AWS_ACCOUNT
AWS_REGION
)
DEPENDENCIES+=(kubectl yq)
REQUIRED_ENV+=()
use cloud/aws/cli
#####################################################################
EKS_CLUSTER_LOGIN() {
EKS__KUBECTL() { EKS kubectl $@; }
EKS__FLUX() { EKS flux $@; }
#####################################################################
EKS() {
local USAGE="
usage: cli [...kubectl args...]
args:
cli a kubectl-style CLI (e.g. kubectl, helm, flux, etc)
Allows access to kubernetes CLI commands by configuring environment
to point to a specific cluster.
"
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT CLUSTER_NAME) DEPENDENCIES=(kubectl $1) CHECK_ENVIRONMENT || return 1
local CONTEXT="arn:aws:eks:${AWS_REGION}:${AWS_ACCOUNT}:cluster/${CLUSTER_NAME}"
local CONTEXT_ARGS=()
case $1 in
helm ) CONTEXT_ARGS+=(--kube-context $CONTEXT) ;;
* ) CONTEXT_ARGS+=(--context $CONTEXT) ;;
esac
$1 ${CONTEXT_ARGS[@]} ${@:2}
}
#####################################################################
EKS__CLUSTER_LOGIN() {
local USAGE="
usage: [...options...]
@ -25,6 +50,7 @@ EKS_CLUSTER_LOGIN() {
cluster in EKS. Also creates the kubeconfig entry if it does not
already exist.
"
REQUIRED_ENV=(AWS_ACCOUNT AWS_REGION) CHECK_ENVIRONMENT || return 1
local CLUSTER_NAME

View File

@ -0,0 +1,116 @@
#####################################################################
DEPENDENCIES+=(eksctl)
REQUIRED_ENV+=()
use cloud/aws/eks
#####################################################################
EKSCTL() {
REQUIRED_ENV=(AWS_PROFILE AWS_REGION) CHECK_ENVIRONMENT || return 1
AWS_PROFILE=$AWS_PROFILE AWS_REGION=$AWS_REGION \
eksctl $@
}
EKSCTL__CREATE_IAMSERVICEACCOUNT() {
local USAGE="
usage: serviceaccount-name namespace [...options...] -- [...'eksctl create iamserviceaccount' args...]
options:
--serviceaccount (required) target k8s:ServiceAccount
--namespace (required) target k8s:Namespace
--role-name (required) name of the IAM role to assign
--force don't check for existing serviceaccount and override any existing configuration
eksctl create iamserviceaccount args:
$(eksctl create iamserviceaccount --help 2>&1 | grep -v -- '--name' | grep -v -- '--namespace' | grep -v -- '--role-name' | sed 's/^/ /')
"
REQUIRED_ENV=(AWS_REGION AWS_ACCOUNT CLUSTER_NAME) CHECK_ENVIRONMENT || return 1
local SERVICEACCOUNT NAMESPACE ROLE_NAME
local FORCE=0
local EKSCTL_ARGS=()
while [[ $# -gt 0 ]]
do
case $1 in
--serviceaccount ) SERVICEACCOUNT=$2; shift 1 ;;
--namespace ) NAMESPACE=$2; shift 1 ;;
--role-name ) ROLE_NAME=$2; shift 1 ;;
--force ) FORCE=1 ;;
-- ) shift 1; break ;;
* ) ERROR "unknown argument '$1'" ;;
esac
shift 1
done
while [[ $# -gt 0 ]]; do EKSCTL_ARGS+=($1); shift 1; done
[ $SERVICEACCOUNT ] || ERROR "--serviceaccount is required"
[ $NAMESPACE ] || ERROR "--namespace is required"
[ $ROLE_NAME ] || ERROR "--role-name is required"
CHECK_ERRORS --no-fail || return 1
##########################################
[[ $FORCE -eq 0 ]] && {
_EKS__CHECK_IAMSERVICEACCOUNT_EXISTS
local EXISTS_STATUS=$?
case $EXISTS_STATUS in
0 )
SUCCESS "'$NAMESPACE/$SERVICEACCOUNT' already configured with '$ROLE_NAME'"
return 0
;;
1 ) ;; # role does not exist yet; continue with rollout
2 )
ERROR "'$NAMESPACE/$SERVICEACCOUNT' has been configured with a different role than '$ROLE_NAME'"
REMINDER "must use --force flag to overwrite"
return 2
;;
esac
}
STATUS "creating iamserviceaccount" \
&& EKSCTL create iamserviceaccount \
--cluster $CLUSTER_NAME \
--namespace $NAMESPACE \
--name $SERVICEACCOUNT \
--role-name $ROLE_NAME \
--override-existing-serviceaccounts \
--approve \
${EKSCTL_ARGS[@]} \
&& SUCCESS "successfully configured '$NAMESPACE/$SERVICEACCOUNT' with IAM role '$ROLE_NAME'" \
|| { ERROR "unable to configure '$NAMESPACE/$SERVICEACCOUNT' with IAM role '$ROLE_NAME' (check cloudformation dashboard for details)"; return 3; }
}
_EKS__CHECK_IAMSERVICEACCOUNT_EXISTS() {
STATUS "checking for existing role-arn"
local CURRENT_ROLE_ARN=$(
EKS__KUBECTL --namespace $NAMESPACE get serviceaccount $SERVICEACCOUNT -o yaml \
| YQ -r '.metadata.annotations["eks.amazonaws.com/role-arn"]' \
| grep -v '^null$' \
)
[ $CURRENT_ROLE_ARN ] || {
STATUS "serviceaccount does not exist or has no configured role"
return 1
}
[[ $CURRENT_ROLE_ARN =~ "$ROLE_NAME$" ]] || {
STATUS "serviceaccount current role does not match desired role:
CURRENT : $CURRENT_ROLE_ARN
DESIRED : arn:aws:iam::${AWS_ACCOUNT}:role/$ROLE_NAME
"
return 2
}
STATUS "serviceaccount current role matches desired role"
return 0
}

View File

@ -65,6 +65,7 @@ HELM__TEMPLATE__GET() {
[ ! $TEMPLATE_OUTPUT ] && EXIT_CODE=1
[[ $RAW -eq 1 ]] && {
[ $USE_CHART_ROOT ] && [[ $USE_CHART_ROOT -eq 1 ]] || HELM_ARGS+=(--show-only $(echo $TEMPLATE_FILENAME | sed "s|^$CHART_ROOT/||"))
[[ $COLORIZE -eq 1 ]] \

View File

@ -27,9 +27,14 @@ HELM__VALIDATE() {
return 1
}
CHART_NAME=$(yq -r .name "$CHART_ROOT/Chart.yaml")
CHART_NAME=$(YQ -r .name "$CHART_ROOT/Chart.yaml")
[[ $TEMPLATE_FILENAME =~ values*.yaml$ ]] && {
[[ $TEMPLATE_FILENAME =~ values.*.yaml$ ]] && {
HELM_ARGS+=(--values $TEMPLATE_FILENAME)
USE_CHART_ROOT=1
}
[[ $TEMPLATE_FILENAME =~ tests/.*.yaml$ ]] && {
HELM_ARGS+=(--values $TEMPLATE_FILENAME)
USE_CHART_ROOT=1
}
@ -54,9 +59,18 @@ _HELM__GET_CHART_ROOT() {
}
_HELM__GET_DEFAULT_VALUES_ARGS() {
for F in \
"$CHART_ROOT/tests/default.yaml" \
"$CHART_ROOT/values.test.yaml" \
"$CHART_ROOT/values.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS=(--values "$F" $HELM_ARGS)
done
for LOCAL_REPOSITORY in $(\
cat "$CHART_ROOT/Chart.yaml" \
| yq -r '.dependencies[] | .repository' \
| YQ -r '.dependencies[] | .repository' \
| grep '^file://' \
| sed 's|file://||' \
)
@ -67,22 +81,13 @@ _HELM__GET_DEFAULT_VALUES_ARGS() {
;
for F in \
"$LOCAL_REPOSITORY_ROOT/values.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.test.yaml" \
"$LOCAL_REPOSITORY_ROOT/tests/default.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.test.yaml" \
"$LOCAL_REPOSITORY_ROOT/values.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS+=(--values "$F")
[ -f "$F" ] && HELM_ARGS=(--values "$F" $HELM_ARGS)
done
done
for F in \
"$CHART_ROOT/values.yaml" \
"$CHART_ROOT/values.test.yaml" \
"$CHART_ROOT/tests/default.yaml" \
;
do
[ -f "$F" ] && HELM_ARGS+=(--values "$F")
done
}

View File

@ -17,6 +17,13 @@ __CHECK_DEPENDENCY() {
$E "application '$1' "$([[ $OPTIONAL -eq 1 ]] && echo preferred || echo required)" but not available on PATH $(__CREDITS $1)"
return 1
}
[[ $DEPENDENCY =~ ^yq$ ]] && {
yq --version | grep -q mikefarah \
|| WARNING 'detected kislyuk/yq but mikefarah/yq is preferred (compatibility may vary)'
}
return 0
}
__CHECK_COREUTILS() {
@ -36,7 +43,7 @@ __CHECK_COREUTILS() {
done
[[ $NON_GNU_DEPENDENCY_COUNT -gt 0 ]] && {
WARNING 'scripts rely on GNU coreutils; functionality may be limited'
WARNING 'scripts rely on GNU coreutils; compatibility may vary'
IS_MACOS && REMINDER 'GNU coreutils can be installed and linked through Homebrew'
}

View File

@ -142,6 +142,7 @@ INPUT() {
Yn() {
PROMPT "$@ [Yn]"
[ $CI ] && { echo y; return 0; }
[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
local Yn; READ -k Yn; echo >&2
[[ $Yn =~ [nN] ]] && return 1 || return 0
@ -150,6 +151,7 @@ Yn() {
yN() {
PROMPT "$@ [yN]"
[ $CI ] && { echo y; return 0; }
[ $__SCWRYPTS_YES ] && [[ $__SCWRYPTS_YES -eq 1 ]] && { echo y; return 0; }
local yN; READ -k yN; echo >&2
[[ $yN =~ [yY] ]] && return 0 || return 1
@ -218,3 +220,12 @@ EDIT() {
$EDITOR $@ </dev/tty >/dev/tty
SUCCESS "finished editing '$1'!"
}
YQ() {
yq --version | grep -q mikefarah || {
yq $@
return $?
}
yq eval '... comments=""' | yq $@
}