From 9e8de560f8705b4be046d5ae4bb4ae48c27a7fb3 Mon Sep 17 00:00:00 2001 From: Julien Bouyoud Date: Sat, 7 Nov 2020 00:25:49 +0100 Subject: [PATCH] feat: implement 'downloader' Signed-off-by: Julien Bouyoud --- .gitignore | 1 + plugin.yaml | 6 + scripts/commands/downloader.sh | 72 +++++++++ scripts/install.sh | 101 ++++++++++++ scripts/lib/file.sh | 26 +++ scripts/lib/file/custom.sh | 6 + .../lib/file/helm-values-getter/Chart.yaml | 3 + .../helm-values-getter/templates/values.yaml | 1 + scripts/lib/file/local.sh | 7 + scripts/lib/file_uri_substitution.sh | 148 ++++++++++++++++++ scripts/lib/http.sh | 11 ++ scripts/run.sh | 33 +++- tests/assets/.keep | 0 tests/assets/CHART-NAME.yaml | 3 + tests/assets/RELEASE-NAME.yaml | 3 + tests/assets/chart.yaml | 3 + tests/assets/git.yaml | 3 + tests/assets/my-release.yaml | 3 + tests/assets/namespace/CHART-NAME.yaml | 3 + tests/assets/namespace/RELEASE-NAME.yaml | 3 + tests/assets/namespace/chart.yaml | 3 + tests/assets/namespace/git.yaml | 3 + tests/assets/namespace/my-release.yaml | 3 + tests/assets/namespace/test.yaml | 3 + tests/assets/namespace/values.yaml | 3 + tests/assets/test.yaml | 3 + tests/assets/values.yaml | 4 + tests/lib/assert-downloader.bash | 32 ++++ tests/lib/helper.bash | 4 +- tests/unit/downloader.bats | 138 +++++++++++++++- tests/unit/help.bats | 6 + 31 files changed, 633 insertions(+), 5 deletions(-) create mode 100644 scripts/commands/downloader.sh create mode 100755 scripts/install.sh create mode 100644 scripts/lib/file.sh create mode 100644 scripts/lib/file/custom.sh create mode 100644 scripts/lib/file/helm-values-getter/Chart.yaml create mode 100644 scripts/lib/file/helm-values-getter/templates/values.yaml create mode 100644 scripts/lib/file/local.sh create mode 100644 scripts/lib/http.sh delete mode 100644 tests/assets/.keep create mode 100644 tests/assets/CHART-NAME.yaml create mode 100644 tests/assets/RELEASE-NAME.yaml create mode 100644 tests/assets/chart.yaml create mode 100644 tests/assets/git.yaml create mode 100644 tests/assets/my-release.yaml create mode 100644 tests/assets/namespace/CHART-NAME.yaml create mode 100644 tests/assets/namespace/RELEASE-NAME.yaml create mode 100644 tests/assets/namespace/chart.yaml create mode 100644 tests/assets/namespace/git.yaml create mode 100644 tests/assets/namespace/my-release.yaml create mode 100644 tests/assets/namespace/test.yaml create mode 100644 tests/assets/namespace/values.yaml create mode 100644 tests/assets/test.yaml create mode 100644 tests/assets/values.yaml create mode 100644 tests/lib/assert-downloader.bash diff --git a/.gitignore b/.gitignore index ffe8346..853efb4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /tests/coverage/ /node_modules/ /repository/ +/.bin/ diff --git a/plugin.yaml b/plugin.yaml index 665e6fe..044e6d6 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -4,9 +4,15 @@ usage: 'Repeatable configuration scheme for Helm Charts' description: 'This plugin provides a convenient way to manage a set of configuration scheme' useTunnel: false command: '$HELM_PLUGIN_DIR/scripts/run.sh' + +hooks: + install: '$HELM_PLUGIN_DIR/scripts/wrapper/run.cmd $HELM_PLUGIN_DIR/scripts/install.sh' + update: '$HELM_PLUGIN_DIR/scripts/wrapper/run.cmd $HELM_PLUGIN_DIR/scripts/install.sh' + platformCommand: - os: windows command: 'cmd /c $HELM_PLUGIN_DIR/scripts/wrapper/sh.cmd $HELM_PLUGIN_DIR/scripts/run.sh' + downloaders: - command: 'scripts/run.sh downloader' protocols: diff --git a/scripts/commands/downloader.sh b/scripts/commands/downloader.sh new file mode 100644 index 0000000..c37ccba --- /dev/null +++ b/scripts/commands/downloader.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env sh + +set -eu + +# Create temporary directory +TMP_DIR="${HELM_CONFIG_SCHEME_TMP_DIR:-$(mktemp -d)}" + +YQ_PATH="${HELM_PLUGIN_DIR}/.bin/" + +_trap_hook() { + unset_subst_args + rm -rf "${TMP_DIR}" +} + +_yq() { + if [ -f "${YQ_PATH}/yq" ]; then + "${YQ_PATH}/yq" "$@" + else + "${YQ_PATH}/yq.exe" "$@" + fi +} + +downloader() { + if [ $# -ne 2 ]; then + log_error "[downloader] Not able to download config, missing args" + exit 2 + fi + uri="${1}" + parent_process_cmd_line="${2}" + + case "${uri}" in + "config://"*) ;; + + *) + log_error "[downloader] URI '${uri}' not supported" + exit 2 + ;; + esac + + scheme_name=$(printf '%s' "${uri}" | sed 's!config://!!') + + if ! repository_scheme_exists "${scheme_name}"; then + log_error "[downloader] Scheme '${scheme_name}' doesn't exists" + exit 2 + fi + + # build parameters + export_subst_args "${parent_process_cmd_line}" + + idx=0 + repository_view_scheme "${scheme_name}" | while read -r file_template; do + log_info "[downloader] Looking for '${file_template}'..." + + eval "file=${file_template}" + # shellcheck disable=SC2154 + file_content="$( (_file_get "${file}" || printf ''))" + + if [ -z "${file_content}" ]; then + log_info "[downloader] Ignored config source : ${file}" + else + log_info "[downloader] Loaded config source : ${file}" + printf '%s\n' "${file_content}" >"${TMP_DIR}/file-${idx}" + idx=$((idx + 1)) + fi + done + + if [ "$(find "${TMP_DIR}" -type f | wc -l)" -le 1 ]; then + cat "${TMP_DIR}/file-0" 2>/dev/null || printf '' + else + _yq merge -x "${TMP_DIR}"/file-* + fi +} diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..473349b --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env sh + +set -eu + +# Path to current directory +SCRIPT_DIR="$(dirname "$0")" + +if [ "$(uname)" = "Darwin" ]; then + if ! command -v realpath >/dev/null; then + brew install coreutils + fi +fi + +YQ_PATH="${HELM_PLUGIN_DIR}/.bin/" +mkdir -p "${YQ_PATH}" + +YQ_DEFAULT_VERSION="3.4.1" +YQ_VERSION="${YQ_VERSION:-"${YQ_DEFAULT_VERSION}"}" + +YQ_PLATFORM="windows" +if [ "$(uname)" = "Darwin" ]; then + YQ_PLATFORM="darwin" +elif [ "$(uname)" = "Linux" ]; then + YQ_PLATFORM="linux" +fi + +YQ_ARCH="386" +if [ "$(uname -m)" = "x86_64" ]; then + YQ_ARCH="amd64" +fi + +YQ_SUFFIX="" +if [ "${YQ_PLATFORM}" = "windows" ]; then + YQ_SUFFIX=".exe" +fi + +YQ_URL="${YQ_URL:-"https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_${YQ_PLATFORM}_${YQ_ARCH}${YQ_SUFFIX}"}" + +# shellcheck disable=SC2034 +YQ_SHA_darwin_amd64="5553d4640550debed5213a5eb6016d3a3485ca8a36e9c71996610280755d5a50" +# shellcheck disable=SC2034 +YQ_SHA_linux_368="ba57700f41cf21bf019af0eec47cf9884f70c25bc5abb0f3347bd42f19609739" +# shellcheck disable=SC2034 +YQ_SHA_linux_amd64="adbc6dd027607718ac74ceac15f74115ac1f3caef68babfb73246929d4ffb23c" +# shellcheck disable=SC2034 +YQ_SHA_windows_368="6292e14b0c199f2bd33e18a8bfe67f100084837163e1e2bc4934bcd7990a5087" +# shellcheck disable=SC2034 +YQ_SHA_windows_amd64="987d31d3a9b75f9cb0f202173aab033d333d2406ba2caa7dba9d16a5204c2167" + +YQ_SHA_DEFAULT_NAME="YQ_SHA_${YQ_PLATFORM}_${YQ_ARCH}" +eval YQ_SHA_DEFAULT="\$${YQ_SHA_DEFAULT_NAME}" +YQ_SHA="${YQ_SHA:-"${YQ_SHA_DEFAULT}"}" + +RED='\033[0;31m' +NOC='\033[0m' + +get_sha_256() { + if [ ! -f "${1}" ]; then + res='' + elif command -v sha256sum >/dev/null; then + res=$(sha256sum "$1") + elif command -v shasum >/dev/null; then + res=$(shasum -a 256 "$1") + else + res='' + fi + + echo "$res" | cut -d ' ' -f 1 +} + +# shellcheck source=scripts/lib/http.sh +. "${SCRIPT_DIR}/lib/http.sh" + +if [ -n "${SKIP_YQ_INSTALL+x}" ] && [ "${SKIP_YQ_INSTALL}" = "true" ]; then + echo "Skipping yq installation." + exit 0 +fi + +YQ_SHA256="$(get_sha_256 "${YQ_PATH}")" + +if [ "${YQ_SHA256}" != "${YQ_SHA}" ] || [ "${YQ_SHA256}" = "" ]; then + echo "Installing/Upgrading yq dependency..." + + if ! download "${YQ_URL}" >/tmp/yq; then + printf "${RED}%s${NOC}\n" "Can't download yq ..." + exit 1 + fi + + YQ_SHA256="$(get_sha_256 /tmp/yq)" + if [ "${YQ_SHA256}" = "${YQ_SHA}" ] || [ "${YQ_SHA256}" = "" ]; then + chmod +x /tmp/yq + mv /tmp/yq "${YQ_PATH}/yq${YQ_SUFFIX}" + else + printf "${RED}%s${NOC}\n" "Checksum mismatch : expected ${YQ_SHA} but was ${YQ_SHA256}" + if [ "${YQ_VERSION}" != "${YQ_DEFAULT_VERSION}" ]; then + printf "${RED}%s${NOC}\n" "Forgot to set YQ_SHA?" + fi + echo "Ignoring ..." + fi + rm -f /tmp/yq +fi diff --git a/scripts/lib/file.sh b/scripts/lib/file.sh new file mode 100644 index 0000000..c5ff983 --- /dev/null +++ b/scripts/lib/file.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +set -eu + +# shellcheck source=scripts/lib/file/local.sh +. "${SCRIPT_DIR}/lib/file/local.sh" + +# shellcheck source=scripts/lib/file/custom.sh +. "${SCRIPT_DIR}/lib/file/custom.sh" + +_file_get_protocol() { + case "$1" in + *://*) + echo "custom" + ;; + *) + echo "local" + ;; + esac +} + +_file_get() { + file_type=$(_file_get_protocol "${1}") + + _file_"${file_type}"_get "$@" +} diff --git a/scripts/lib/file/custom.sh b/scripts/lib/file/custom.sh new file mode 100644 index 0000000..ae2e69a --- /dev/null +++ b/scripts/lib/file/custom.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +_file_custom_get() { + helm template "${SCRIPT_DIR}/lib/file/helm-values-getter" -f "${1}" | + sed -E -e "s/^# Source: .+$//" -e "s/^---$//" +} diff --git a/scripts/lib/file/helm-values-getter/Chart.yaml b/scripts/lib/file/helm-values-getter/Chart.yaml new file mode 100644 index 0000000..fea58ff --- /dev/null +++ b/scripts/lib/file/helm-values-getter/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: helm-values-getter +version: 1.0.0 diff --git a/scripts/lib/file/helm-values-getter/templates/values.yaml b/scripts/lib/file/helm-values-getter/templates/values.yaml new file mode 100644 index 0000000..4bdbf9d --- /dev/null +++ b/scripts/lib/file/helm-values-getter/templates/values.yaml @@ -0,0 +1 @@ +{{- .Values | toYaml -}} diff --git a/scripts/lib/file/local.sh b/scripts/lib/file/local.sh new file mode 100644 index 0000000..421a8b1 --- /dev/null +++ b/scripts/lib/file/local.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +set -eu + +_file_local_get() { + cat "${1}" 2>/dev/null +} diff --git a/scripts/lib/file_uri_substitution.sh b/scripts/lib/file_uri_substitution.sh index 1455f9c..ff46eb3 100644 --- a/scripts/lib/file_uri_substitution.sh +++ b/scripts/lib/file_uri_substitution.sh @@ -36,3 +36,151 @@ file_uri_subst() { echo "${file_uri}" | sed 's/{{/${/g' | sed 's/}}/}/g' } + +unset_subst_args() { + unset namespace chart release +} + +export_subst_args() { + # shellcheck disable=SC2034 + export namespace="${HELM_NAMESPACE:-unknown}" + # shellcheck disable=SC2034 + export chart="CHART-NAME" + # shellcheck disable=SC2034 + export release="RELEASE-NAME" + # shellcheck disable=SC2086 + _get_subst_args_value ${1} + + # Refine chart value + if [ -d "${chart}" ]; then + chart="$(realpath "${chart}")" + fi + chart="$(basename "${chart}")" + # Remove Semver + chart="$(echo "${chart}" | sed -E 's/(.+)-[0-9]+\.[0-9]+\.[0-9]+(-.+)?/\1/')" + # Remove ext + chart="${chart%%.*}" + + log_info "[substitution] Args namespace=${namespace}, chart=${chart}, release=${release}" +} + +_get_subst_args_value() { + args="" + + # Remove all flags, and put all args into var + i=1 + while [ "$i" -le "$#" ]; do + eval "arg=\${$i}" + # shellcheck disable=SC2154 + is_flag="$(_is_helm_flag "${arg}")" + + if [ "${is_flag}" -gt 0 ]; then + i=$((i + is_flag)) + else + args="${args} ${arg}" + i=$((i + 1)) + fi + done + + log_info "[substitution] analyzing arguments $args" + # shellcheck disable=SC2086 + set -- $args + + while [ $# -gt 0 ]; do + case "${1:-}" in + lint) + return + ;; + template) + if [ $# -ge 3 ]; then + release="${2}" + chart="${3}" + else + chart="${2}" + fi + return + ;; + install | upgrade) + release="${2}" + chart="${3}" + return + ;; + esac + shift + done +} + +_is_helm_flag() { + case "${1:-}" in + # Global Flags :: Key, Value + --repository-config | --repository-cache | --registry-config | -n | --namespace | \ + --kubeconfig | --kube-token | --kube-context | --kube-as-user | --kube-as-group | \ + --kube-apiserver) + echo 2 + ;; + # Global Flags :: Key + -h | --help | --debug) + echo 1 + ;; + # Value Options Flags https://github.com/helm/helm/blob/master/cmd/helm/flags.go#L41 + -f | --values | --set | --set-string | --set-file) + echo 2 + ;; + # ChartPathOptionsFlags https://github.com/helm/helm/blob/master/cmd/helm/flags.go#L48 + --version | --keyring | --repo | --username | --password | --cert-file | --key-file | --ca-file) + echo 2 + ;; + --verify | --insecure-skip-tls-verify) + echo 1 + ;; + # https://github.com/helm/helm/blob/master/cmd/helm/flags.go#L63 + -o | --output | --post-renderer) + echo 2 + ;; + # Lint flags + --strict | --with-subcharts) + echo 1 + ;; + # Install Flags + --create-namespace | --dry-run | --no-hooks | --replace | --wait | --devel | \ + --dependency-update | --disable-openapi-validation | --atomic | --skip-crds | \ + --render-subchart-notes) + echo 1 + ;; + --timeout | --description) + echo 2 + ;; + -g | --generate-name) + log_error " Unable to proceed repeatable configuration with a generated name" + return 2 + ;; + --name-template) + log_error " name-template flag is not supported" + return 2 + ;; + # Template Flags + -s | --show-only | --output-dir | --api-versions | --release-name) + echo 2 + ;; + --validate | --include-crds | --is-upgrade) + echo 1 + ;; + # Upgrade Flags + --history-max) + # Already existing + # --timeout | --description + echo 2 + ;; + -i | --install | --recreate-pods | --force | --reset-values | \ + --reuse-values | --cleanup-on-fail) + # Already existing + # --create-namespace | --devel | --dry-run | --no-hooks | + # --disable-openapi-validation | --skip-crds | + # --wait | --atomic | --render-subchart-notes + echo 1 + ;; + *) + echo 0 + ;; + esac +} diff --git a/scripts/lib/http.sh b/scripts/lib/http.sh new file mode 100644 index 0000000..201008c --- /dev/null +++ b/scripts/lib/http.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh + +download() { + if command -v curl >/dev/null; then + curl -sSfL "$1" + elif command -v wget >/dev/null; then + wget -q -O- "$1" + else + return 1 + fi +} diff --git a/scripts/run.sh b/scripts/run.sh index 378b82a..052e80c 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -20,6 +20,9 @@ HELM_BIN="${HELM_BIN:-helm}" # shellcheck source=scripts/lib/repository.sh . "${SCRIPT_DIR}/lib/repository.sh" +# shellcheck source=scripts/lib/file.sh +. "${SCRIPT_DIR}/lib/file.sh" + _trap_hook() { true } @@ -48,6 +51,20 @@ Configuration scheme usage with : 'config://' EOF } +_parent_process_command() { + if [ "$(uname)" = "Darwin" ]; then + ps -p "${PPID}" -o command= + elif [ "$(uname)" = "Linux" ]; then + if command -v apk >/dev/null; then + # alpine based + # shellcheck disable=SC2009 + ps -o pid,args= | grep -E "^\s+${PPID}" | awk '!($1="")' + else + ps -p "${PPID}" -o command= + fi + fi +} + while true; do case "${1:-}" in add | edit | list | remove | view) @@ -63,8 +80,20 @@ while true; do break ;; downloader) - log_error "Error: Not yet implemented." - exit 2 + # command certFile keyFile caFile full-URL + if [ $# -le 4 ]; then + log_error "[downloader] invalid usage, please refer to https://helm.sh/docs/topics/plugins/#downloader-plugins" + exit 1 + fi + # shellcheck source=scripts/commands/downloader.sh + . "${SCRIPT_DIR}/commands/downloader.sh" + + # retrieve original helm command line + HELM_COMMAND="$(_parent_process_command)" + + # It's always the 5th parameter + downloader "${5}" "${HELM_COMMAND}" + break ;; --help | -h | help) usage diff --git a/tests/assets/.keep b/tests/assets/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/assets/CHART-NAME.yaml b/tests/assets/CHART-NAME.yaml new file mode 100644 index 0000000..ab28e6a --- /dev/null +++ b/tests/assets/CHART-NAME.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/CHART-NAME.yaml: 'true' diff --git a/tests/assets/RELEASE-NAME.yaml b/tests/assets/RELEASE-NAME.yaml new file mode 100644 index 0000000..e090f69 --- /dev/null +++ b/tests/assets/RELEASE-NAME.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/RELEASE-NAME.yaml: 'true' diff --git a/tests/assets/chart.yaml b/tests/assets/chart.yaml new file mode 100644 index 0000000..cda59b5 --- /dev/null +++ b/tests/assets/chart.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/chart.yaml: 'true' diff --git a/tests/assets/git.yaml b/tests/assets/git.yaml new file mode 100644 index 0000000..7f620d0 --- /dev/null +++ b/tests/assets/git.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/git.yaml: 'true' diff --git a/tests/assets/my-release.yaml b/tests/assets/my-release.yaml new file mode 100644 index 0000000..b439749 --- /dev/null +++ b/tests/assets/my-release.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/my-release.yaml: 'true' diff --git a/tests/assets/namespace/CHART-NAME.yaml b/tests/assets/namespace/CHART-NAME.yaml new file mode 100644 index 0000000..17f4fb6 --- /dev/null +++ b/tests/assets/namespace/CHART-NAME.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/CHART-NAME.yaml: 'true' diff --git a/tests/assets/namespace/RELEASE-NAME.yaml b/tests/assets/namespace/RELEASE-NAME.yaml new file mode 100644 index 0000000..4e3f6d7 --- /dev/null +++ b/tests/assets/namespace/RELEASE-NAME.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/RELEASE-NAME.yaml: 'true' diff --git a/tests/assets/namespace/chart.yaml b/tests/assets/namespace/chart.yaml new file mode 100644 index 0000000..18fc12a --- /dev/null +++ b/tests/assets/namespace/chart.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/chart.yaml: 'true' diff --git a/tests/assets/namespace/git.yaml b/tests/assets/namespace/git.yaml new file mode 100644 index 0000000..187ad6c --- /dev/null +++ b/tests/assets/namespace/git.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/git.yaml: 'true' diff --git a/tests/assets/namespace/my-release.yaml b/tests/assets/namespace/my-release.yaml new file mode 100644 index 0000000..ce045a9 --- /dev/null +++ b/tests/assets/namespace/my-release.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/my-release.yaml: 'true' diff --git a/tests/assets/namespace/test.yaml b/tests/assets/namespace/test.yaml new file mode 100644 index 0000000..332d1cb --- /dev/null +++ b/tests/assets/namespace/test.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/test.yaml: 'true' diff --git a/tests/assets/namespace/values.yaml b/tests/assets/namespace/values.yaml new file mode 100644 index 0000000..c7e4f3d --- /dev/null +++ b/tests/assets/namespace/values.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + ns/values.yaml: 'true' diff --git a/tests/assets/test.yaml b/tests/assets/test.yaml new file mode 100644 index 0000000..3deb2d7 --- /dev/null +++ b/tests/assets/test.yaml @@ -0,0 +1,3 @@ +ingress: + annotations: + default/test.yaml: 'true' diff --git a/tests/assets/values.yaml b/tests/assets/values.yaml new file mode 100644 index 0000000..32f1102 --- /dev/null +++ b/tests/assets/values.yaml @@ -0,0 +1,4 @@ +ingress: + enabled: true + annotations: + default/values.yaml: 'true' diff --git a/tests/lib/assert-downloader.bash b/tests/lib/assert-downloader.bash new file mode 100644 index 0000000..917113f --- /dev/null +++ b/tests/lib/assert-downloader.bash @@ -0,0 +1,32 @@ + +assert-downloader-output-base() { + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/rand-assets/values.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/values.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${chart}.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${release}.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${CUSTOM_ENV_VAR}.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${namespace}/values.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${namespace}/\${chart}.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${namespace}/\${release}.yaml'..." + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/\${namespace}/\${CUSTOM_ENV_VAR}.yaml'..." + + assert_file_not_exist "${HELM_CONFIG_SCHEME_TMP_DIR}" +} + +assert-downloader-output() { + assert-downloader-output-base + + namespace="${1}" + chart="${2}" + release="${3}" + env="${4}" + assert_output --partial "[config-scheme][downloader] Ignored config source : ${TEST_TEMP_DIR}/rand-assets/values.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/values.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${chart}.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${release}.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${env}.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${namespace}/values.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${namespace}/${chart}.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${namespace}/${release}.yaml" + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/${namespace}/${env}.yaml" +} diff --git a/tests/lib/helper.bash b/tests/lib/helper.bash index 75fba95..5708dba 100644 --- a/tests/lib/helper.bash +++ b/tests/lib/helper.bash @@ -38,6 +38,9 @@ setup() { # Use a temporary config-repository reseted after every suite export HELM_CONFIG_SCHEME_REPOSITORY="${TEST_TEMP_DIR}/config-repository" + export HELM_CONFIG_SCHEME_TMP_DIR="${TEST_TEMP_DIR}/config-tmp" + + mkdir -p "${HELM_CONFIG_SCHEME_TMP_DIR}" # shellcheck disable=SC2034 XDG_DATA_HOME="${HOME}" @@ -48,7 +51,6 @@ setup() { APPDATA="${HOME}" # install helm plugin - helm_plugin_install git helm plugin install "${GIT_ROOT}" # copy .kube from real home diff --git a/tests/unit/downloader.bats b/tests/unit/downloader.bats index d0f3bf9..78354b8 100644 --- a/tests/unit/downloader.bats +++ b/tests/unit/downloader.bats @@ -4,9 +4,143 @@ load '../lib/helper' load '../bats/extensions/bats-support/load' load '../bats/extensions/bats-assert/load' load '../bats/extensions/bats-file/load' +load '../lib/assert-downloader' -@test "downloader:" { +@test "downloader: invalid usage" { run helm config-scheme downloader + assert_failure 1 + assert_output --partial '[config-scheme][downloader] invalid usage, please refer to' + + run helm config-scheme downloader unused + assert_failure 1 + assert_output --partial '[config-scheme][downloader] invalid usage, please refer to' + + run helm config-scheme downloader unused unused + assert_failure 1 + assert_output --partial '[config-scheme][downloader] invalid usage, please refer to' + + run helm config-scheme downloader unused unused unused + assert_failure 1 + assert_output --partial '[config-scheme][downloader] invalid usage, please refer to' +} + +@test "downloader: not supported uri" { + run helm config-scheme downloader unused unused unused git://test assert_failure 2 - assert_output --partial 'Error: Not yet implemented.' + assert_output --partial "[config-scheme][downloader] URI 'git://test' not supported" +} + +@test "downloader: config scheme not found" { + run helm config-scheme downloader unused unused unused config://random + assert_failure 2 + assert_output --partial "[config-scheme][downloader] Scheme 'random' doesn't exists" +} + +@test "downloader: nominal one file in config" { + if is_windows; then + skip + fi + + helm config-scheme add test "${TEST_TEMP_DIR}/assets/values.yaml" + + run helm config-scheme downloader unused unused unused config://test -n namespace 2>&1 + assert_success + assert_file_not_exist "${HELM_CONFIG_SCHEME_TMP_DIR}" + assert_output --partial "[config-scheme][downloader] Looking for '${TEST_TEMP_DIR}/assets/values.yaml'..." + assert_output --partial "[config-scheme][downloader] Loaded config source : ${TEST_TEMP_DIR}/assets/values.yaml" + + assert_output --partial "$(cat <<-YAML +ingress: + enabled: true + annotations: + default/values.yaml: 'true' +YAML +)" + refute_output --partial 'default/CHART-NAME.yaml:' + refute_output --partial 'default/my-chart.yaml:' + refute_output --partial 'default/RELEASE-NAME.yaml:' + refute_output --partial 'default/my-release.yaml:' + refute_output --partial 'default/test.yaml:' + refute_output --partial 'default/git.yaml:' + refute_output --partial 'ns/default.yaml:' + refute_output --partial 'ns/CHART-NAME.yaml:' + refute_output --partial 'ns/my-chart.yaml:' + refute_output --partial 'ns/RELEASE-NAME.yaml:' + refute_output --partial 'ns/my-release.yaml:' + refute_output --partial 'ns/test.yaml:' + refute_output --partial 'ns/git.yaml:' +} + +@test "downloader: nominal only with local files" { + if is_windows; then + skip + fi + + create_config_scheme test + + run helm config-scheme downloader unused unused unused config://test -n namespace 2>&1 + assert_success + assert-downloader-output "namespace" "CHART-NAME" "RELEASE-NAME" "test" + + assert_output --partial "$(cat <<-YAML +ingress: + enabled: true + annotations: + default/values.yaml: 'true' + default/CHART-NAME.yaml: 'true' + default/RELEASE-NAME.yaml: 'true' + default/test.yaml: 'true' + ns/values.yaml: 'true' + ns/CHART-NAME.yaml: 'true' + ns/RELEASE-NAME.yaml: 'true' + ns/test.yaml: 'true' +YAML +)" + + refute_output --partial 'default/my-chart.yaml:' + refute_output --partial 'default/my-release.yaml:' + refute_output --partial 'default/git.yaml:' + refute_output --partial 'ns/my-chart.yaml:' + refute_output --partial 'ns/my-release.yaml:' + refute_output --partial 'ns/git.yaml:' + +} + +@test "downloader: nominal" { + if is_windows; then + skip + fi + helm_plugin_install git + + create_config_scheme test + helm config-scheme edit test append \ + "git+https://github.com/jBouyoud/helm-config-scheme@{{chart}}.yaml?ref=master" \ + "git+https://github.com/jBouyoud/helm-config-scheme@tests/assets/git.yaml?ref=first-release" \ + "git+https://github.com/jBouyoud/helm-config-scheme@tests/assets/{{namespace}}/git.yaml?ref=first-release" + + run helm config-scheme downloader unused unused unused config://test -n namespace 2>&1 + assert_success + assert-downloader-output "namespace" "CHART-NAME" "RELEASE-NAME" "test" + + assert_output --partial "$(cat <<-YAML +ingress: + enabled: true + annotations: + default/values.yaml: 'true' + default/CHART-NAME.yaml: 'true' + default/RELEASE-NAME.yaml: 'true' + default/test.yaml: 'true' + ns/values.yaml: 'true' + ns/CHART-NAME.yaml: 'true' + ns/RELEASE-NAME.yaml: 'true' + ns/test.yaml: 'true' + default/git.yaml: "true" + ns/git.yaml: "true" +YAML +)" + + refute_output --partial 'default/my-chart.yaml:' + refute_output --partial 'default/my-release.yaml:' + refute_output --partial 'ns/my-chart.yaml:' + refute_output --partial 'ns/my-release.yaml:' } diff --git a/tests/unit/help.bats b/tests/unit/help.bats index 53bfd62..ec9c897 100755 --- a/tests/unit/help.bats +++ b/tests/unit/help.bats @@ -9,6 +9,12 @@ load '../bats/extensions/bats-file/load' run helm plugin list assert_success assert_output --partial 'config-scheme' + + if is_windows; then + assert_file_exist ".bin/yq.exe" + else + assert_file_exist ".bin/yq" + fi } @test "help: helm config-scheme show help" {