|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | +shopt -s inherit_errexit |
| 5 | + |
| 6 | +module_acceptance() { |
| 7 | + if [[ "${#}" -lt 2 ]] || [[ ! "${1}" =~ ^(sc|wc)$ ]]; then |
| 8 | + log_fatal "usage: module_acceptance <sc|wc> <module_name> [<helm-post-renderer-kustomization-dir>]" |
| 9 | + fi |
| 10 | + |
| 11 | + log_info "Running module acceptance test by comparing existing Helm Release ${2} in cluster ${1} with Module ${2}" |
| 12 | + |
| 13 | + local crossplane_release |
| 14 | + local release_namespace |
| 15 | + local chart_repository |
| 16 | + local chart_name |
| 17 | + local chart_version |
| 18 | + local values |
| 19 | + |
| 20 | + crossplane_release="$(_crossplane_render "${1}" "${2}" | yq 'select(.kind == "Release")')" |
| 21 | + |
| 22 | + crossplane_release_external_name=$(yq '.metadata.annotations["crossplane.io/external-name"]' <<<"${crossplane_release}") |
| 23 | + if [ "${crossplane_release_external_name}" != "${2}" ]; then |
| 24 | + log_error "Annotation 'crossplane.io/external-name' in Release in Module ${2} does not match existing Helm Release name" |
| 25 | + log_error "Expected: ${2}" |
| 26 | + log_error "Actual: ${crossplane_release_external_name}" |
| 27 | + log_fatal "DO NOT UPGRADE" |
| 28 | + fi |
| 29 | + |
| 30 | + release_namespace=$(yq '.spec.forProvider.namespace' <<<"${crossplane_release}") |
| 31 | + chart_repository=$(yq '.spec.forProvider.chart.repository' <<<"${crossplane_release}") |
| 32 | + chart_name=$(yq '.spec.forProvider.chart.name' <<<"${crossplane_release}") |
| 33 | + chart_version=$(yq '.spec.forProvider.chart.version' <<<"${crossplane_release}") |
| 34 | + values="$(yq -o json '.spec.forProvider.values' <<<"${crossplane_release}")" |
| 35 | + |
| 36 | + # FIXME: Currently null |
| 37 | + release_namespace="kube-system" |
| 38 | + |
| 39 | + helm_diff_args=( |
| 40 | + -n "${release_namespace}" |
| 41 | + upgrade "${2}" "${chart_repository}/${chart_name}" |
| 42 | + --version "${chart_version}" |
| 43 | + --allow-unreleased |
| 44 | + --reset-values |
| 45 | + --values - |
| 46 | + --detailed-exitcode |
| 47 | + --normalize-manifests |
| 48 | + ) |
| 49 | + |
| 50 | + [[ "${#}" -gt 2 ]] && |
| 51 | + helm_diff_args+=( |
| 52 | + --post-renderer "${ROOT}/scripts/helm-kustomize-post-renderer.sh" |
| 53 | + --post-renderer-args "${3}" |
| 54 | + ) |
| 55 | + |
| 56 | + if ! echo "${values}" | helm_do "${1}" diff "${helm_diff_args[@]}"; then |
| 57 | + log_error "Detected unexpected differences between the existing Helm Release '${2}' and the Module '${2}'." |
| 58 | + log_fatal "DO NOT UPGRADE" |
| 59 | + fi |
| 60 | + |
| 61 | + log_info "Module ${2} acceptance test for cluster ${1} succeeded!" |
| 62 | +} |
| 63 | + |
| 64 | +_crossplane_render() { |
| 65 | + if [[ "${#}" -lt 2 ]] || [[ ! "${1}" =~ ^(sc|wc)$ ]]; then |
| 66 | + log_fatal "usage: _crossplane_render <sc|wc> <module_name>" |
| 67 | + fi |
| 68 | + |
| 69 | + log_info "Rendering Module ${2}" |
| 70 | + |
| 71 | + local tmpdir |
| 72 | + tmpdir="$(mktemp -d)" |
| 73 | + |
| 74 | + append_trap 'rm -r '"${tmpdir}" EXIT |
| 75 | + |
| 76 | + _crossplane_composition "${1}" "${2}" >"${tmpdir}/composition.yaml" |
| 77 | + |
| 78 | + _crossplane_functions "${1}" >"${tmpdir}/functions.yaml" |
| 79 | + |
| 80 | + _crossplane_xr "${1}" "${2}" >"${tmpdir}/xr.yaml" |
| 81 | + |
| 82 | + crossplane render "${tmpdir}/xr.yaml" "${tmpdir}/composition.yaml" "${tmpdir}/functions.yaml" |
| 83 | +} |
| 84 | + |
| 85 | +_crossplane_composition() { |
| 86 | + if [[ "${#}" -lt 2 ]] || [[ ! "${1}" =~ ^(sc|wc)$ ]]; then |
| 87 | + log_fatal "usage: _crossplane_composition <sc|wc> <module_name>" |
| 88 | + fi |
| 89 | + |
| 90 | + log_info "Extracting Composition from Module ${2}'s Configuration package" |
| 91 | + |
| 92 | + local tmpdir |
| 93 | + tmpdir="$(mktemp -d)" |
| 94 | + |
| 95 | + append_trap 'rm -r '"${tmpdir}" EXIT |
| 96 | + |
| 97 | + local configuration_package |
| 98 | + configuration_package=$(helmfile_do "${1}" template -l name=crossplane-packages | yq 'select(.kind == "Configuration" and .metadata.name == "'"module-${2}"'").spec.package') |
| 99 | + |
| 100 | + if [ -z "${configuration_package}" ]; then |
| 101 | + log_fatal "Failed to determine Configuration package from Module ${2}" |
| 102 | + fi |
| 103 | + |
| 104 | + log_info "Found Configuration package: ${configuration_package}" |
| 105 | + |
| 106 | + crossplane xpkg extract "${configuration_package}" -o "${tmpdir}/out.gz" |
| 107 | + |
| 108 | + zcat "${tmpdir}/out.gz" | yq 'select(.kind == "Composition")' |
| 109 | +} |
| 110 | + |
| 111 | +_crossplane_functions() { |
| 112 | + if [[ ! "${1}" =~ ^(sc|wc)$ ]]; then |
| 113 | + log_fatal "usage: _crossplane_functions <sc|wc>" |
| 114 | + fi |
| 115 | + |
| 116 | + log_info "Getting Crossplane Functions that should be installed by Apps" |
| 117 | + |
| 118 | + helmfile_do "${1}" template -l name=crossplane-packages | yq 'select(.kind == "Function")' |
| 119 | +} |
| 120 | + |
| 121 | +_crossplane_xr() { |
| 122 | + if [[ "${#}" -lt 2 ]] || [[ ! "${1}" =~ ^(sc|wc)$ ]]; then |
| 123 | + log_fatal "usage: _crossplane_xr <sc|wc> <module_name>" |
| 124 | + fi |
| 125 | + |
| 126 | + log_info "Getting Crossplane XR from Module ${2}" |
| 127 | + |
| 128 | + helmfile_do "${1}" template -l "name=module-${2}" |
| 129 | +} |
0 commit comments