rancher-partner-charts/scripts/prepare-subcharts

139 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -e
# Pull in the subcharts required by a chart
#
# At the end of this process, all the required subcharts will exist in the charts/charts directory.
# Charts will either exist as chart archives (i.e. a .tgz file) if they are not eligible for patches or
# as a local chart archive (i.e. a directory) if they are eligible for patches (i.e. remote subchart with fixed version number)
#
# In order to prepare sub-charts so that we can patch them:
# - We apply any patches on the requirements.yaml to track any new subcharts added via patch or updates to version numbers of the subcharts
# - We pull in any subchart that is a feature chart by running prepare on it
# - We copy in any local subcharts that are located in the overlay/ directory
# - We call `helm dependency update` to generate chart archives (.tgz files) for local and remote charts
# - We clean up any copied charts from the overlay/ directory
# - We clean up any feature charts that were recursively prepared
# - We unarchive the chart archive if and only if its a remote subchart with a fixed version number (which means it can be patched)
# - We revert the initial patch we applied on the requirements.yaml
if [[ -z $1 ]]; then
echo "No directory provided to pull in subcharts"
exit 1
fi
f=$1
if ! [[ -f ${f}/charts/requirements.yaml ]]; then
echo "Chart ${CHART} has no dependencies; skipping step to pull in dependencies"
exit 0
fi
# Apply the patch on the requirements.yaml
for file in $(find ./${f} -type f -name "*.patch"); do
# This awk statement extracts the contents between the first line that matches the regex `diff.*requirements.yaml`
# and the first line that matches the regex `diff` after it. This corresponds to the contents of any patches on the requirements.yaml file.
awk '/diff.*requirements.yaml/{flag=1;next}/diff/{flag=0}flag' $file >> ${f}/requirements.patch
done
if [[ -f ${f}/requirements.patch ]] && [[ -s ${f}/requirements.patch ]]; then
patch -E -p3 -d ${f}/charts < ${f}/requirements.patch
fi
# Pull in any dependencies that are stored as package.yamls or in the overlay/ folder
overlaid_dependencies=()
mirrored_dependencies=()
i=0
while ! [[ -z $(yq r ${f}/charts/requirements.yaml "dependencies[${i}]") ]]; do
repo=$(yq r ${f}/charts/requirements.yaml "dependencies[${i}].repository")
if [[ ${repo} == file://* ]]; then
charts_path=${repo/file:\/\//${f}/charts/}
if [[ -d ${charts_path} ]]; then
# Chart already exists
((i=i+1))
continue
fi
if [[ -f ${charts_path%/*}/package.yaml ]]; then
# Prepare the subchart and pull it in
subchart=$(basename -- ${charts_path%/*})
mirrored_dependencies+=("${subchart}")
prepare_subchart () {
local CURRENT_CHART=${CHART}
local CURRENT_INDEX=${i}
CHART=${subchart} ./scripts/prepare
CHART=${CURRENT_CHART}
i=${CURRENT_INDEX}
}
prepare_subchart
fi
overlay_path=${repo/file:\/\//${f}/overlay/}
if [[ -d $overlay_path ]]; then
# Pull in the subchart from the overlay/ directory
cp -R $overlay_path $charts_path
overlaid_dependencies+=("${charts_path}")
fi
fi
((i=i+1))
done
# Update the current requirements.lock and requirements.yaml to keep track of the overlay/ dependencies
pwd=$(pwd)
cd ${f}/charts
helm dependency update
cd $pwd
# Remove any dependencies that came from the overlay/ directory, we don't track patches for overlay files
for dep in "${overlaid_dependencies[@]}"; do
rm -rf $dep
done
# Cleanup any dependencies that came from another local chart, any changes should be made there.
for subchart in "${mirrored_dependencies[@]}"; do
cleanup_subchart () {
local CURRENT_CHART=${CHART}
CHART=${subchart} ./scripts/clean
CHART=${CURRENT_CHART}
}
cleanup_subchart
done
if ! [[ -d ${f}/charts/charts ]]; then
exit 0
fi
# If it is possible to patch a subchart, create a local chart archive for it
# Otherwise, it should only be stored as a tgz file to prevent users from accidentally patching it
i=0
while ! [[ -z $(yq r ${f}/charts/requirements.yaml "dependencies[${i}]") ]]; do
name=$(yq r ${f}/charts/requirements.yaml "dependencies[${i}].name")
version=$(yq r ${f}/charts/requirements.yaml "dependencies[${i}].version")
repo=$(yq r ${f}/charts/requirements.yaml "dependencies[${i}].repository")
if [[ ${repo} == file://* ]]; then
# Subcharts that are tracked locally should be directly edited, not via a patch
rm -rf ${f}/charts/charts/${name}
((i=i+1))
continue
fi
if [[ ! ${version} =~ ^[0-9\.]+$ ]]; then
# Subcharts that are tracked remotely must have a fixed version number
rm -rf ${f}/charts/charts/${name}
((i=i+1))
continue
fi
# Subchart could be patched
subchart_tgz=${name}-${version}.tgz
if [[ -f ${f}/charts/charts/${subchart_tgz} ]]; then
tar xvzf ${f}/charts/charts/${subchart_tgz} -C ${f}/charts/charts > /dev/null 2>&1
rm ${f}/charts/charts/${subchart_tgz}
fi
((i=i+1))
done
# Undo the patch on the requirements.yaml
if [[ -f ${f}/requirements.patch ]]; then
if [[ -s ${f}/requirements.patch ]]; then
# Should only apply a patch if the requirements.patch has something in it
patch -R -E -p3 -d ${f}/charts < ${f}/requirements.patch
fi
rm ${f}/requirements.patch
fi