Skip to content

Instantly share code, notes, and snippets.

@bgulla
Last active December 19, 2024 05:18
Show Gist options
  • Save bgulla/69839e781b975e59b86881663b9b0095 to your computer and use it in GitHub Desktop.
Save bgulla/69839e781b975e59b86881663b9b0095 to your computer and use it in GitHub Desktop.
Chart.yaml -> Hauler Manifest Tool
#!/bin/bash
# This script pulls a Helm chart from an OCI registry or uses a local Chart.yaml file,
# extracts container images defined in the `helm.sh/images` annotation of the Chart.yaml,
# and generates a Hauler Images manifest.
OCI_LOCATION=""
OUTPUT_FILE=""
LOCAL_CHART=""
SOURCE_REGISTRY=""
HELM_USERNAME=""
HELM_PASSWORD=""
USE_STDOUT=false
COSIGN_KEY=""
PLATFORM=""
HAULER_REGISTRY=""
HELM_VERSION=""
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--local-chart)
LOCAL_CHART=$2
shift 2
;;
--registry)
SOURCE_REGISTRY=$2
shift 2
;;
--helm-username)
HELM_USERNAME=$2
shift 2
;;
--helm-password)
HELM_PASSWORD=$2
shift 2
;;
--cosign-key)
COSIGN_KEY=$2
shift 2
;;
--platform)
PLATFORM=$2
shift 2
;;
--hauler-registry)
HAULER_REGISTRY=$2
shift 2
;;
--helm-version)
HELM_VERSION=$2
shift 2
;;
--stdout)
USE_STDOUT=true
shift
;;
--help)
grep '^# ' "$0" | sed 's/^# //'
exit 0
;;
*)
if [ -z "$OCI_LOCATION" ]; then
OCI_LOCATION=$1
elif [ -z "$OUTPUT_FILE" ]; then
OUTPUT_FILE=$1
else
echo "Error: Unknown argument: $1"
exit 1
fi
shift
;;
esac
done
# Validate arguments
if [ -z "$LOCAL_CHART" ] && [ -z "$OCI_LOCATION" ]; then
echo "Error: Either --local-chart or <oci-location> must be specified."
exit 1
fi
if [ "$USE_STDOUT" = false ] && [ -z "$OUTPUT_FILE" ]; then
echo "Error: Either --stdout or <output-file> must be specified."
exit 1
fi
# Optional Helm registry authentication
if [ -n "$HELM_USERNAME" ] && [ -n "$HELM_PASSWORD" ]; then
helm registry login --username "$HELM_USERNAME" --password "$HELM_PASSWORD" "$(echo "$OCI_LOCATION" | awk -F'/' '{print $3}')"
if [ $? -ne 0 ]; then
echo "Error: Failed to log into Helm registry."
exit 1
fi
fi
# Determine the source of Chart.yaml
if [ -n "$LOCAL_CHART" ]; then
CHART_FILE="$LOCAL_CHART"
else
TEMP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_DIR" EXIT
# Add version flag if specified
HELM_PULL_ARGS=("$OCI_LOCATION" --untar --untardir "$TEMP_DIR")
if [ -n "$HELM_VERSION" ]; then
HELM_PULL_ARGS+=(--version "$HELM_VERSION")
fi
helm pull "${HELM_PULL_ARGS[@]}"
if [ $? -ne 0 ]; then
echo "Failed to pull Helm chart from $OCI_LOCATION"
exit 1
fi
CHART_FILE=$(find "$TEMP_DIR" -name "Chart.yaml")
if [ -z "$CHART_FILE" ]; then
echo "Error: Chart.yaml not found in the pulled chart."
exit 1
fi
fi
CHART_CONTENT=$(cat "$CHART_FILE")
if [ -z "$CHART_CONTENT" ]; then
echo "Error: Unable to read Chart.yaml."
exit 1
fi
IMAGES=$(echo "$CHART_CONTENT" | yq eval '.annotations."helm.sh/images"' -)
if [ $? -ne 0 ]; then
echo "Error: Failed to parse annotations.helm.sh/images from Chart.yaml content"
exit 1
fi
IMAGES_LIST=$(echo "$IMAGES" | yq eval '.' -)
if [ $? -ne 0 ]; then
echo "Error: Failed to process images block into structured YAML"
exit 1
fi
{
cat <<EOF
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Images
metadata:
name: hauler-content-images-example
EOF
if [ -n "$COSIGN_KEY" ] || [ -n "$PLATFORM" ] || [ -n "$HAULER_REGISTRY" ]; then
cat <<EOF
annotations:
EOF
[ -n "$COSIGN_KEY" ] && echo " hauler.dev/key: $COSIGN_KEY"
[ -n "$PLATFORM" ] && echo " hauler.dev/platform: $PLATFORM"
[ -n "$HAULER_REGISTRY" ] && echo " hauler.dev/registry: $HAULER_REGISTRY"
fi
cat <<EOF
spec:
images:
EOF
echo "$IMAGES_LIST" | yq eval -o=json '.' - | jq -r '.[] | " - name: \(.image)"'
} > "${OUTPUT_FILE:-/dev/stdout}"
@bgulla
Copy link
Author

bgulla commented Dec 18, 2024

Usage:

> bash helm-to-hauler-manifest.sh oci://registry.suse.com/private-registry/harbor output.yaml
Pulled: registry.suse.com/private-registry/harbor:1.15.1
Digest: sha256:1bb0656f64e1f872dad3bb357cbc5ee15c5445f8433a59e052a26abc09dcfd49
> cat output.yaml
apiVersion: content.hauler.cattle.io/v1alpha1
kind: Images
metadata:
  name: hauler-content-images-example
  annotations:
    hauler.dev/key: <cosign-public-key>
    hauler.dev/platform: <platform>
    hauler.dev/registry: <registry>
spec:
  images:
    - name: registry.suse.com/private-registry/harbor-nginx:2.11
    - name: registry.suse.com/private-registry/harbor-core:2.11
    - name: registry.suse.com/private-registry/harbor-db:2.11
    - name: registry.suse.com/private-registry/harbor-exporter:2.11
    - name: registry.suse.com/private-registry/harbor-jobservice:2.11
    - name: registry.suse.com/private-registry/harbor-portal:2.11
    - name: registry.suse.com/private-registry/harbor-registry:2.11
    - name: registry.suse.com/private-registry/harbor-registryctl:2.11
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:2.11
    - name: registry.suse.com/private-registry/harbor-redis:7.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment