From 0aa4ce38e17eb628b21c77b8fcacd03eecf77904 Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Wed, 9 Feb 2022 11:20:33 -0800 Subject: [PATCH 1/2] Inject version requirement and bundle ID into charts Signed-off-by: Brad Davidson --- Dockerfile | 5 ++++- charts/build-chart.sh | 25 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e42bb4e7ce..11fa202ac7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,9 @@ RUN set -x \ gcc \ bsd-compat-headers \ py-pip \ - pigz + pigz \ + tar \ + yq # Dapper/Drone/CI environment FROM build AS dapper @@ -92,6 +94,7 @@ VOLUME /var/lib/rancher/k3s FROM build AS charts ARG CHART_REPO="https://rke2-charts.rancher.io" +ARG KUBERNETES_VERSION="" ARG CACHEBUST="cachebust" COPY charts/ /charts/ RUN echo ${CACHEBUST}>/dev/null diff --git a/charts/build-chart.sh b/charts/build-chart.sh index aeb5f0a35c..0af43dd105 100755 --- a/charts/build-chart.sh +++ b/charts/build-chart.sh @@ -2,11 +2,34 @@ set -eux -o pipefail +: "${KUBERNETES_VERSION:=v0.0.0-0}" : "${CHART_FILE?required}" : "${CHART_NAME:="$(basename "${CHART_FILE%%.yaml}")"}" : "${CHART_PACKAGE:="${CHART_NAME%%-crd}"}" +: "${TAR_OPTS:=--owner=0 --group=0 --mode=gou-s+r --numeric-owner --no-acls --no-selinux --no-xattrs}" : "${CHART_URL:="${CHART_REPO:="https://rke2-charts.rancher.io"}/assets/${CHART_PACKAGE}/${CHART_NAME}-${CHART_VERSION:="v0.0.0"}.tgz"}" -curl -fsSL "${CHART_URL}" -o "${CHART_TMP:=$(mktemp)}" +: "${CHART_TMP:=$(mktemp --suffix .tar.gz)}" +: "${YAML_TMP:=$(mktemp --suffix .yaml)}" + +cleanup() { + exit_code=$? + trap - EXIT INT + rm -rf ${CHART_TMP} ${CHART_TMP/tar.gz/tar} ${YAML_TMP} + exit ${exit_code} +} +trap cleanup EXIT INT + +curl -fsSL "${CHART_URL}" -o "${CHART_TMP}" +gunzip ${CHART_TMP} + +# Extract out Chart.yaml, inject a version requirement and bundle-id annotation, and delete/replace the one in the original tarball +tar -xOf ${CHART_TMP/.gz/} ${CHART_NAME}/Chart.yaml > ${YAML_TMP} +yq -i e ".kubeVersion = \">= ${KUBERNETES_VERSION}\" | .annotations.\"fleet.cattle.io/bundle-id\" = \"rke2\"" ${YAML_TMP} +tar --delete -b 8192 -f ${CHART_TMP/.gz/} ${CHART_NAME}/Chart.yaml +tar --transform="s|.*|${CHART_NAME}/Chart.yaml|" ${TAR_OPTS} -vrf ${CHART_TMP/.gz/} ${YAML_TMP} + +pigz -11 ${CHART_TMP/.gz/} + cat <<-EOF > "${CHART_FILE}" apiVersion: helm.cattle.io/v1 kind: HelmChart From 6a3500f1421fa2d3e9ee2c53dc18601c3edce448 Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Wed, 9 Feb 2022 14:51:58 -0800 Subject: [PATCH 2/2] Don't rewrite manifests when values don't change Signed-off-by: Brad Davidson --- pkg/bootstrap/bootstrap.go | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index d3dcd21a16..56ff24b3ac 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -1,9 +1,11 @@ package bootstrap import ( + "bytes" "crypto/sha256" "encoding/hex" "fmt" + "io" "io/ioutil" "os" "path/filepath" @@ -295,13 +297,13 @@ func setChartValues(manifestsDir string, nodeConfig *daemonconfig.Node, cfg cmds // If the file cannot be decoded as a HelmChart, it is silently skipped. Any other IO error is considered // a failure. func rewriteChart(fileName string, info os.FileInfo, chartValues map[string]string, serializer *json.Serializer) error { - bytes, err := ioutil.ReadFile(fileName) + b, err := ioutil.ReadFile(fileName) if err != nil { return errors.Wrapf(err, "Failed to read manifest %s", fileName) } // Ignore manifest if it cannot be decoded - obj, _, err := serializer.Decode(bytes, nil, nil) + obj, _, err := serializer.Decode(b, nil, nil) if err != nil { logrus.Debugf("Failed to decode manifest %s: %s", fileName, err) return nil @@ -321,21 +323,37 @@ func rewriteChart(fileName string, info os.FileInfo, chartValues map[string]stri chart.Spec.Set = map[string]intstr.IntOrString{} } + var changed bool for k, v := range chartValues { - chart.Spec.Set[k] = intstr.FromString(v) + val := intstr.FromString(v) + if cur, ok := chart.Spec.Set[k]; ok { + curBytes, _ := cur.MarshalJSON() + newBytes, _ := val.MarshalJSON() + if bytes.Equal(curBytes, newBytes) { + continue + } + } + changed = true + chart.Spec.Set[k] = val } - f, err := os.OpenFile(fileName, os.O_RDWR|os.O_TRUNC, info.Mode()) - if err != nil { - return errors.Wrapf(err, "Unable to open HelmChart %s", fileName) + if !changed { + logrus.Infof("No cluster configuration value changes necessary for HelmChart %s", fileName) + return nil } - if err := serializer.Encode(chart, f); err != nil { - _ = f.Close() + var buf bytes.Buffer + if err := serializer.Encode(chart, &buf); err != nil { return errors.Wrapf(err, "Failed to serialize modified HelmChart %s", fileName) } - if err := f.Close(); err != nil { + f, err := os.OpenFile(fileName, os.O_RDWR|os.O_TRUNC, info.Mode()) + if err != nil { + return errors.Wrapf(err, "Unable to open HelmChart %s", fileName) + } + defer f.Close() + + if _, err := io.Copy(f, &buf); err != nil { return errors.Wrapf(err, "Failed to write modified HelmChart %s", fileName) }