#!/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