Skip to content

Commit

Permalink
Add script for bundling images for airgap
Browse files Browse the repository at this point in the history
Signed-off-by: Kyle Squizzato <[email protected]>
  • Loading branch information
squizzi committed Oct 11, 2024
1 parent 8bad252 commit 8f23c9b
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ CHARTS_PACKAGE_DIR ?= $(LOCALBIN)/charts
$(CHARTS_PACKAGE_DIR): | $(LOCALBIN)
rm -rf $(CHARTS_PACKAGE_DIR)
mkdir -p $(CHARTS_PACKAGE_DIR)
IMAGES_PACKAGE_DIR ?= $(LOCALBIN)/images
$(IMAGES_PACKAGE_DIR): | $(LOCALBIN)
rm -rf $(IMAGES_PACKAGE_DIR)
mkdir -p $(IMAGES_PACKAGE_DIR)
PACKAGE_FOR_AIRGAP ?= false

TEMPLATE_FOLDERS = $(patsubst $(TEMPLATES_DIR)/%,%,$(wildcard $(TEMPLATES_DIR)/*))

Expand All @@ -150,6 +155,9 @@ lint-chart-%:
$(HELM) lint --strict $(TEMPLATES_SUBDIR)/$*

package-chart-%: lint-chart-%
@if [ $(PACKAGE_FOR_AIRGAP) ]; then \
echo $(TEMPLATES_SUBDIR)/$*; \
fi
$(HELM) package --destination $(CHARTS_PACKAGE_DIR) $(TEMPLATES_SUBDIR)/$*

LD_FLAGS?= -s -w
Expand Down Expand Up @@ -347,6 +355,9 @@ dev-aws-nuke: envsubst awscli yq cloud-nuke ## Warning: Destructive! Nuke all AW
.PHONY: cli-install
cli-install: clusterawsadm clusterctl cloud-nuke envsubst yq awscli ## Install the necessary CLI tools for deployment, development and testing.

.PHONY: airgap-package
airgap-package: ## Generate Helm chart and Docker image tarballs for air-gapped environments.

##@ Dependencies

## Location to install dependencies to
Expand Down Expand Up @@ -414,6 +425,7 @@ HELM_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/helm/helm/master/scrip
$(HELM): | $(LOCALBIN)
rm -f $(LOCALBIN)/helm-*
curl -s $(HELM_INSTALL_SCRIPT) | USE_SUDO=false HELM_INSTALL_DIR=$(LOCALBIN) DESIRED_VERSION=$(HELM_VERSION) BINARY_NAME=helm-$(HELM_VERSION) PATH="$(LOCALBIN):$(PATH)" bash
$(HELM) plugin install https://github.com/nikhilsbhat/helm-images

$(FLUX_HELM_CRD): $(EXTERNAL_CRD_DIR)
rm -f $(FLUX_HELM_CRD)
Expand Down
142 changes: 142 additions & 0 deletions scripts/bundle-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash
# Copyright 2024
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# bundle-images.sh bundles all of the images used across HMC into a single
# tarball. This is useful for deploying HMC into air-gapped environments.
# It is recommended to use this script in conjunction with the Makefile target
# `make bundle-images` which will perform some additional steps outside of
# this scripts functionality.
# Usage: make bundle-images

if [ -z $YQ ]; then
echo "YQ must be set to the path of the yq binary"
echo "Use 'make bundle-images' instead of running this script directly to populate this value"
exit 1
fi

if [ -z $HELM ]; then
echo "HELM must be set to the path of the helm binary"
echo "Use 'make bundle-images' instead of running this script directly to populate this value"
exit 1
fi

if [ -z $KIND_CLUSTER_NAME ]; then
echo "KIND_CLUSTER_NAME must be set to the name of the kind cluster"
echo "Use 'make bundle-images' instead of running this script directly to populate this value"
exit 1
fi

if [ -z $NAMESPACE ]; then
echo "NAMESPACE must be set to the namespace where HMC is deployed"
echo "Use 'make bundle-images' instead of running this script directly to populate this value"
exit 1
fi

if [ -z $BUNDLE_TARBALL ]; then
echo "BUNDLE_TARBALL must be set to the name of the tarball to create"
echo "Use 'make bundle-images' instead of running this script directly to populate this value"
exit 1
fi

LABEL_KEY="cluster.x-k8s.io/provider"
IMAGES_BUNDLED=""

# Verify each provider we support has deployed so we can get the images used
# across the deployments.
for TEMPLATE in
$(ls templates/provider/*/templates/provider*.yaml)
do
PROVIDER_YAML=$(grep -P '(?=.*Provider)(?=.*kind)' -A 2 $TEMPLATE | grep -v '\--')
PROVIDER_KIND=$(echo $PROVIDER | $YQ e '.kind',,)
PROVIDER_NAME=$(echo $PROVIDER | $YQ e '.metadata.name')
PROVIDER_KIND_TOLOWER=$(echo ${KIND,,})

# controlplane is a special case which needs a hyphen.
if [[ $PROVIDER_KIND_TOLOWER == "controlplane" ]]; then
PROVIDER_KIND_TOLOWER="control-plane"
fi

LABEL_VALUE=$(echo $($PROVIDER_KIND_TOLOWER | sed -e 's/provider//g')-$PROVIDER_NAME)

kubectl wait --for condition=available --timeout=2m deploy -l $LABEL_KEY=$LABEL_VALUE -n $NAMESPACE
done


# Now that we know everything is deployed and ready, we can get all of images by
# execing into the KIND cluster.
CONTROL_PLANE=$(kubectl get nodes --no-headers -o custom-columns=":metadata.name")

for IMAGE in
$(docker exec -it $CONTROL_PLANE crictl images | sed 1,1d | awk '{print $1":"$2}' | grep -v "kindest")
do
docker pull $IMAGE && docker save $IMAGE -o $BUNDLE_TARBALL_NAME
echo $IMAGE >> $IMAGES_BUNDLED
done


# Next, we need to build a list of images used by k0s extensions. Walk the
# templates directory and extract the images used by the extensions.
for TEMPLATE in
$(find ./templates -name 'k0s*.yaml')
do
if [[ $TEMPLATE == *"k0smotron"* ]]; then
EXTENSIONS_PATH=".spec.k0sConfig.spec.extensions.helm"
else
EXTENSIONS_PATH=".spec.k0sConfigSpec.k0s.spec.extensions.helm"
fi

REPOS=grep -vw "{{" $TEMPLATE |
$YQ e "${EXTENSIONS_PATH}.repositories[] | [.url, .name] | join(\";\")"
for REPO in $REPOS
do
URL=$(echo $REPO | cut -d';' -f1)
NAME=$(echo $REPO | cut -d';' -f2)

VERSION=$(grep -vw "{{" $TEMPLATE |
$YQ e "${EXTENSIONS_PATH}.charts[] | select(.name == \"$NAME\") | .version")

VALUES=$(grep -vw "{{" $TEMPLATE |
$YQ e "${EXTENSIONS_PATH}.charts[] | select(.name == \"$NAME\") | .values")

if [[ $VALUES != "null" ]]; then
# Check to see if a custom image is being used.
CUSTOM_TAG=$(echo $VALUES | $YQ e '.image.tag')
fi

# Use 'helm template' to get the images used by the extension.
for IMAGE in $(HELM) template --repo $URL --version $VERSION $NAME | grep -Eo | cut -d' ' -f2
do
if [[ -z $CUSTOM_TAG ]]; then
IMAGE=$(echo $IMAGE | sed -e "s/:.*$/:$CUSTOM_TAG/")
fi

docker pull $IMAGE && docker save $IMAGE -o $BUNDLE_TARBALL_NAME
echo $IMAGE >> $IMAGES_BUNDLED
done
done
done

# Cleanup the images bundled by removing them from the local image cache.
for IMAGE in $IMAGES_BUNDLED
do
echo "Removing $IMAGE from local image cache"
docker rmi $IMAGE
done




#grep -vw "{{" templates/cluster/aws-hosted-cp/templates/k0smotroncontrolplane.yaml | ./bin/yq-v4.44.2 -e '.spec.k0sConfig.spec.extensions.helm.charts[] | select(.name == "aws-cloud-controller-manager") | .version'
#grep -vw "{{" templates/cluster/aws-hosted-cp/templates/k0smotroncontrolplane.yaml | ./bin/yq-v4.44.2 -e '.spec.k0sConfig.spec.extensions.helm.charts[] | select(.name == "aws-cloud-controller-manager") | .values' | ./bin/yq-v4.44.2 -e '.image.tag'

0 comments on commit 8f23c9b

Please sign in to comment.