703 lines
23 KiB
Bash
Executable File
703 lines
23 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
set -o pipefail
|
|
set -o nounset
|
|
|
|
# global vars
|
|
CHART_NAME_OPERATOR=""
|
|
ELEMENTAL_OPERATOR_CRDS_CHART_NAME="\$ELEMENTAL_CRDS_CHART"
|
|
CHANNEL_IMAGE_VAR=""
|
|
CHANNEL_IMAGE_VAL=""
|
|
IMAGES_TO_SAVE=""
|
|
HAULER_REG_DIR=$(mktemp -d)
|
|
HAULER_REG_PID=""
|
|
HAULER_REG_DUMMY_FILE="hauler-registry.txt"
|
|
|
|
: ${CONTAINER_IMAGES_NAME:="elemental-images"}
|
|
: ${CONTAINER_IMAGES_FILE:=$CONTAINER_IMAGES_NAME".txt"}
|
|
: ${CONTAINER_IMAGES_ARCHIVE:=$CONTAINER_IMAGES_NAME".tar.gz"}
|
|
: ${DEBUG:="false"}
|
|
: ${HAULER:="false"}
|
|
: ${HAULER_STORE:=$(pwd)"/elemental-collection"}
|
|
: ${LOCAL_REGISTRY:=\$LOCAL_REGISTRY}
|
|
: ${CHART_NAME_CRDS:=$ELEMENTAL_OPERATOR_CRDS_CHART_NAME}
|
|
: ${CHART_VERSION:="latest"}
|
|
: ${CHANNEL_ONLY:="false"}
|
|
: ${CHANNEL_IMAGE_NAME:="\$CHANNEL_IMAGE_NAME"}
|
|
: ${SKIP_ARCHIVE_CREATION:="false"}
|
|
: ${ALL_CHANNELS:="false"}
|
|
|
|
print_help() {
|
|
cat <<- EOF
|
|
Usage: $0 [OPTION] -r LOCAL_REGISTRY ELEMENTAL_OPERATOR_CHART
|
|
[-ac|-all-channels] add all defined ManagedOSVersionChannel.
|
|
[-c|--crds-chart] Elemental CRDS chart (if URL, will be downloaded).
|
|
[-co|--channel-only] just extract and rebuild the ManagedOSVersionChannel container image.
|
|
[-cv|--chart-version] specify the chart version (only used if passing chart as URLs).
|
|
[-d|--debug] enable debug output on screen.
|
|
[-i|--images path] tar.gz gernerated by docker save.
|
|
[-h|--help] usage message.
|
|
[-ha|--hauler] use hauler to generate the archive (an "Haul") of the Elemental "Collection".
|
|
[-l|--image-list path] generated text file with the list of saved images (one image per line).
|
|
[-r|--local-registry] registry where to load the images to (used in the next steps).
|
|
[-sa|--skip-archive] put the list of images in the $CONTAINER_IMAGES_FILE but skip $CONTAINER_IMAGES_ARCHIVE creation.
|
|
|
|
ELEMENTAL_OPERATOR_CHART could be either a chart tgz file or an url (in that case will be downloaded first)
|
|
it could even be 'dev', 'staging' or 'stable' to allow automatic download of the charts.
|
|
|
|
Parameters could also be set passing env vars:
|
|
ALL_CHANNELS (-ac) : $ALL_CHANNELS
|
|
CONTAINER_IMAGES_NAME : $CONTAINER_IMAGES_NAME
|
|
CONTAINER_IMAGES_FILE (-l) : $CONTAINER_IMAGES_FILE
|
|
CONTAINER_IMAGES_ARCHIVE (-i) : $CONTAINER_IMAGES_ARCHIVE
|
|
DEBUG (-d) : $DEBUG
|
|
LOCAL_REGISTRY (-r) : $LOCAL_REGISTRY
|
|
CHART_NAME_CRDS (-c) : $CHART_NAME_CRDS
|
|
CHART_VERSION (-cv) : $CHART_VERSION
|
|
CHANNEL_ONLY (-co) : $CHANNEL_ONLY
|
|
CHANNEL_IMAGE_NAME : $CHANNEL_IMAGE_NAME
|
|
SKIP_ARCHIVE_CREATION (-sa) : $SKIP_ARCHIVE_CREATION
|
|
|
|
examples:
|
|
|
|
$0 -r $LOCAL_REGISTRY staging
|
|
|
|
$0 oci://registry.opensuse.org/isv/rancher/elemental/staging/charts/rancher/elemental-operator-chart \\
|
|
-c oci://registry.opensuse.org/isv/rancher/elemental/staging/charts/rancher/elemental-operator-crds-chart \\
|
|
-r $LOCAL_REGISTRY
|
|
|
|
# For creating an Hauler haul
|
|
$0 -ha -r $LOCAL_REGISTRY stable
|
|
EOF
|
|
}
|
|
|
|
parse_parameters() {
|
|
|
|
local help="false"
|
|
local container_images_archive="false"
|
|
|
|
POSITIONAL=()
|
|
while [[ $# -gt 0 ]]; do
|
|
key="$1"
|
|
case $key in
|
|
-i|--images)
|
|
CONTAINER_IMAGES_ARCHIVE="$2"
|
|
container_images_archive="true"
|
|
shift # past argument
|
|
shift # past value
|
|
;;
|
|
-l|--image-list)
|
|
CONTAINER_IMAGES_FILE="$2"
|
|
shift # past argument
|
|
shift # past value
|
|
;;
|
|
-c|--crds-chart)
|
|
CHART_NAME_CRDS="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
-cv|--chart-version)
|
|
CHART_VERSION="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
-r|--local-registry)
|
|
LOCAL_REGISTRY="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
-co|--channel-only)
|
|
CHANNEL_ONLY=true
|
|
shift
|
|
;;
|
|
-sa|--skip-archive)
|
|
SKIP_ARCHIVE_CREATION=true
|
|
shift
|
|
;;
|
|
-d|--debug)
|
|
DEBUG="true"
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
help="true"
|
|
shift
|
|
;;
|
|
-ha|--hauler)
|
|
HAULER="true"
|
|
if [[ "${container_images_archive}" == "false" ]]; then
|
|
CONTAINER_IMAGES_ARCHIVE="elemental-haul.tar.zst"
|
|
fi
|
|
shift
|
|
;;
|
|
-ac|--all-channels)
|
|
ALL_CHANNELS=true
|
|
shift
|
|
;;
|
|
*)
|
|
[[ -n "$CHART_NAME_OPERATOR" ]] && exit_error "unrecognized command: $1"
|
|
CHART_NAME_OPERATOR="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
if [[ "$help" = "true" ]]; then
|
|
print_help
|
|
exit 0
|
|
fi
|
|
if [[ -z "$CHART_NAME_OPERATOR" ]]; then
|
|
print_help
|
|
echo ""
|
|
exit_error "ELEMENTAL_OPERATOR_CHART is a required argument"
|
|
fi
|
|
if [[ "$LOCAL_REGISTRY" == "\$LOCAL_REGISTRY" ]]; then
|
|
print_help
|
|
echo ""
|
|
exit_error "LOCAL_REGISTRY is required"
|
|
fi
|
|
case "$CHART_NAME_OPERATOR" in
|
|
Dev|dev|DEV)
|
|
CHART_NAME_OPERATOR="oci://registry.opensuse.org/isv/rancher/elemental/dev/charts/rancher/elemental-operator-chart"
|
|
[[ "$CHART_NAME_CRDS" == "$ELEMENTAL_OPERATOR_CRDS_CHART_NAME" ]] && \
|
|
CHART_NAME_CRDS="oci://registry.opensuse.org/isv/rancher/elemental/dev/charts/rancher/elemental-operator-crds-chart"
|
|
;;
|
|
Maintenance|maintenance|MAINTENANCE)
|
|
# For now, we have to hardcode the 6.0 path, we will have to add a parameter to choose between 6.0 and 6.1
|
|
CHART_NAME_OPERATOR="oci://registry.opensuse.org/isv/rancher/elemental/maintenance/6.0/charts/rancher/elemental-operator-chart"
|
|
[[ "$CHART_NAME_CRDS" == "$ELEMENTAL_OPERATOR_CRDS_CHART_NAME" ]] && \
|
|
CHART_NAME_CRDS="oci://registry.opensuse.org/isv/rancher/elemental/maintenance/6.0/charts/rancher/elemental-operator-crds-chart"
|
|
;;
|
|
Staging|staging|STAGING)
|
|
CHART_NAME_OPERATOR="oci://registry.opensuse.org/isv/rancher/elemental/staging/charts/rancher/elemental-operator-chart"
|
|
[[ "$CHART_NAME_CRDS" == "$ELEMENTAL_OPERATOR_CRDS_CHART_NAME" ]] && \
|
|
CHART_NAME_CRDS="oci://registry.opensuse.org/isv/rancher/elemental/staging/charts/rancher/elemental-operator-crds-chart"
|
|
;;
|
|
Stable|stable|STABLE)
|
|
CHART_NAME_OPERATOR="oci://registry.suse.com/rancher/elemental-operator-chart"
|
|
[[ "$CHART_NAME_CRDS" == "$ELEMENTAL_OPERATOR_CRDS_CHART_NAME" ]] && \
|
|
CHART_NAME_CRDS="oci://registry.suse.com/rancher/elemental-operator-crds-chart"
|
|
;;
|
|
esac
|
|
|
|
}
|
|
|
|
exit_error() {
|
|
eval msg=\"$1\"
|
|
echo -e "ERR: $msg"
|
|
is_hauler && hauler_stop_local_registry
|
|
exit 1
|
|
}
|
|
|
|
log_debug() {
|
|
[[ "$DEBUG" == "false" ]] && return 0
|
|
eval msg=\'${1}\'
|
|
echo -e "$msg"
|
|
}
|
|
|
|
log_info() {
|
|
eval msg=\"$1\"
|
|
echo -e "$msg"
|
|
}
|
|
|
|
is_hauler() {
|
|
[[ "${HAULER}" != "false" ]] && return 0 || return 1
|
|
}
|
|
|
|
# get_chart_val "VARNAME" "CHARTVAR" ["false"]
|
|
# Retrieves CHARTVAR from the chart and puts the value in VARNAME.
|
|
# If CHARTVAR is not found in the chart, it will error and exit, BUT if the optional third parameter
|
|
# is passed and is == "false" would just log the missing value and not terminate the script.
|
|
get_chart_val() {
|
|
local local_var="$1"
|
|
local local_val="$2"
|
|
local local_fail=${3:-"true"}
|
|
local local_condition="[[ \"\$$local_var\" == \"null\" ]]"
|
|
|
|
eval $local_var='$(helm show values $CHART_NAME_OPERATOR | eval yq '.${local_val}' | sed s/\"//g 2>&1)'
|
|
if eval $local_condition; then
|
|
if [[ "$local_fail" == "false" ]]; then
|
|
log_debug "cannot find $local_val in $CHART_NAME_OPERATOR"
|
|
eval $local_var=""
|
|
return 0
|
|
fi
|
|
exit_error "cannot find \$local_val in $CHART_NAME_OPERATOR (likely not an elemental-operator chart with airgap support)"
|
|
fi
|
|
eval log_debug \"extracted $local_var\\t: \$$local_var\ \($local_val\)\"
|
|
}
|
|
|
|
# get_json_val "VARNAME" "JSONDATA" "JSONFIELD"
|
|
# receives a json data snippet as JSONDATA and the json field to retrieve as JSONFIELD.
|
|
# puts the value extracted in a variable called as VARNAME.
|
|
get_json_val() {
|
|
local local_var="$1"
|
|
local jsondata="$2"
|
|
local local_val="$3"
|
|
|
|
eval $local_var=$(echo $jsondata | jq $local_val)
|
|
eval log_debug \"extracted $local_var\\t: \$$local_var\ \($local_val\)\"
|
|
}
|
|
|
|
# set_json_val "VARNAME" "JSONDATA" "JSONFIELD" "VALUE"
|
|
# sets JSONFIELD to VALUE in the received JSONDATA json snippet and outputs the changed json data in
|
|
# variable VARNAME
|
|
set_json_val() {
|
|
local local_var="$1"
|
|
local jsondata="$2"
|
|
local json_field="$3"
|
|
local local_val="$4"
|
|
|
|
log_debug "set $json_field to $local_val"
|
|
eval $local_var=\'$(echo $jsondata | jq $json_field=\"$local_val\")\'
|
|
eval log_debug \"\$$local_var\"
|
|
}
|
|
|
|
# add_image_to_export_list
|
|
# this just adds the passed image to the list of the images to be saved in the images list text file and
|
|
# in the tar.gz archive containing the saved images to be loaded in the local registry.
|
|
add_image_to_export_list() {
|
|
is_hauler && return 0
|
|
local img="${1}"
|
|
if [[ -z "${img}" ]]; then
|
|
log_debug "cannot add image to export list: empty image passed"
|
|
return 0
|
|
fi
|
|
case "${IMAGES_TO_SAVE} " in
|
|
*" ${img} "*)
|
|
log_debug "skip adding image to export list: '$img' already added"
|
|
;;
|
|
*)
|
|
log_debug "mark '$img' image for export"
|
|
IMAGES_TO_SAVE="$IMAGES_TO_SAVE $img"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
prereq_checks() {
|
|
log_debug "Check required binaries availability"
|
|
local cmd_list="helm yq jq sed docker"
|
|
is_hauler && cmd_list="${cmd_list} hauler"
|
|
for cmd in $cmd_list; do
|
|
if ! command -v "$cmd" > /dev/null; then
|
|
exit_error "'$cmd' not found."
|
|
fi
|
|
log_debug "$cmd found"
|
|
done
|
|
}
|
|
|
|
fetch_charts() {
|
|
local outstr charts="CHART_NAME_OPERATOR"
|
|
|
|
[[ "$CHART_NAME_CRDS" != "$ELEMENTAL_OPERATOR_CRDS_CHART_NAME" ]] && charts="${charts} CHART_NAME_CRDS"
|
|
|
|
for c in $charts; do
|
|
local chart=""
|
|
local chart_ver=""
|
|
local opts=""
|
|
|
|
# helm pull only supports semver tags: for the "latest" tag just don't put the version.
|
|
[[ "$CHART_VERSION" != "latest" ]] && chart_ver="--version $CHART_VERSION"
|
|
|
|
# helm pull needs to be aware of development versions
|
|
[[ "${CHART_NAME_OPERATOR}" =~ (Dev|dev|DEV|Staging|staging|STAGING) ]] && opts="--devel"
|
|
|
|
# 'c' var holds the name (e.g., CHART_NAME_OPERATOR),
|
|
# 'chart' var holds the value (e.g., elemental-operator-chart-1.4.tgz)
|
|
eval chart=\$$c
|
|
case $chart in
|
|
"oci://"*|"https//"*)
|
|
log_debug "fetching chart '$chart' $chart_ver"
|
|
if ! outstr=$(helm pull ${opts} ${chart} $chart_ver 2>&1); then
|
|
exit_error "downloading ${chart}:\n $outstr"
|
|
fi
|
|
eval $c=$(ls -t1 | head -n 1)
|
|
log_info "Downloaded Elemental Operator chart: \$$c"
|
|
if is_hauler; then
|
|
eval hauler_store_add_file "\$$c"
|
|
fi
|
|
;;
|
|
*)
|
|
[[ ! -f "$chart" ]] && exit_error "chart file $chart not found"
|
|
log_debug "using chart $chart"
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
pull_chart_container_images() {
|
|
local oprtimg_repo oprtimg_tag seedimg_repo seedimg_tag registry_url
|
|
|
|
[[ "$CHANNEL_ONLY" == "true" ]] && return 0
|
|
|
|
get_chart_val oprtimg_repo "image.repository"
|
|
get_chart_val oprtimg_tag "image.tag"
|
|
get_chart_val seedimg_repo "seedImage.repository"
|
|
get_chart_val seedimg_tag "seedImage.tag"
|
|
get_chart_val source_registry "registryUrl"
|
|
|
|
for img in "${oprtimg_repo}:${oprtimg_tag}" "${seedimg_repo}:${seedimg_tag}"; do
|
|
[[ -z "$img" ]] && continue
|
|
|
|
if is_hauler; then
|
|
hauler_store_add_image "${source_registry}/${img}"
|
|
continue
|
|
elif pull_image "${source_registry}/${img}"; then
|
|
docker tag "${source_registry}/${img}" "${img}"
|
|
add_image_to_export_list "${img}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
pull_image() {
|
|
local image_url="$1"
|
|
|
|
[[ -z "$image_url" ]] && return 1
|
|
if docker pull "$image_url" > /dev/null 2>&1; then
|
|
log_info "Image pull success: ${image_url}"
|
|
else
|
|
if docker inspect "$image_url" > /dev/null 2>&1; then
|
|
log_debug "error downloading ${image_url} but the image is saved"
|
|
else
|
|
log_info "Image pull failed: ${image_url}"
|
|
return 1
|
|
fi
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
|
|
build_os_channel() {
|
|
local channel_img
|
|
local channel_tag="latest"
|
|
local channel_repo
|
|
local channel_list
|
|
|
|
log_info "Creating OS channel"
|
|
# name of the new channel container image we are going to create
|
|
if [[ "${CHANNEL_IMAGE_NAME}" == "\$CHANNEL_IMAGE_NAME" ]]; then
|
|
CHANNEL_IMAGE_NAME="rancher/elemental-channel-${LOCAL_REGISTRY%:*}"
|
|
fi
|
|
|
|
# defaultChannels has been introduced in 1.7 version
|
|
# we can directly add the images in channel_list
|
|
get_chart_val channel_list "defaultChannels" "false"
|
|
if [ -n "$channel_list" ]; then
|
|
get_chart_val channel_list "defaultChannels[].image" "false"
|
|
fi
|
|
|
|
if [[ -z "$channel_list" ]]; then
|
|
# v1.4+ chart
|
|
#
|
|
# channel.repository was changed to channel.image around 1.4 - 1.5 versions
|
|
# channel.image contains the full URL (with registry) while channel.repository not (full URL by prepending with registryUrl)
|
|
# example, full image URL: registry.suse.com/rancher/elemental-channel
|
|
# - operator < v1.4
|
|
# . channel.repository = "rancher/elemental-channel"
|
|
# . registryUrl = "registry.suse.com"
|
|
# - operator > v1.4
|
|
# . channel.image = "registry.suse.com/rancher/elemental-channel"
|
|
#
|
|
# we want in channel_img the full image URL for both cases
|
|
get_chart_val channel_img "channel.image" "false"
|
|
|
|
if [[ -z "$channel_img" ]]; then
|
|
# legacy chart
|
|
get_chart_val channel_img "channel.repository"
|
|
get_chart_val channel_repo "registryUrl"
|
|
channel_img=${channel_repo}/${channel_img}
|
|
CHANNEL_IMAGE_VAR="channel.repository"
|
|
CHANNEL_IMAGE_VAL=${CHANNEL_IMAGE_NAME}
|
|
else
|
|
CHANNEL_IMAGE_VAR="channel.image"
|
|
CHANNEL_IMAGE_VAL=${LOCAL_REGISTRY}/${CHANNEL_IMAGE_NAME}
|
|
fi
|
|
|
|
get_chart_val channel_tag "channel.tag"
|
|
channel_list+="${channel_img}:${channel_tag} "
|
|
else
|
|
# This defined the local channel image
|
|
CHANNEL_IMAGE_VAR="channel.image"
|
|
CHANNEL_IMAGE_VAL=${LOCAL_REGISTRY}/${CHANNEL_IMAGE_NAME}
|
|
fi
|
|
|
|
# we can have OS channels added in templates, so we have to sync them if needed
|
|
if [[ "$ALL_CHANNELS" == "true" ]]; then
|
|
# get all ManagedOSVersionChannel, so the already extracted one is in, we can overwrite channel_list
|
|
channel_list=$(helm template $CHART_NAME_OPERATOR \
|
|
| yq 'select(.kind=="ManagedOSVersionChannel") .spec.options.image' \
|
|
| sed -e s/\"//g -e /^---$/d 2>&1)
|
|
fi
|
|
|
|
if [[ -z "${channel_list// /}" ]]; then
|
|
log_info "\nWARNING: channel image not found: you will need to provide your own Elemental OS images\n"
|
|
return 0
|
|
fi
|
|
|
|
TEMPDIR=$(mktemp -d)
|
|
log_debug "build channel image in $TEMPDIR"
|
|
pushd $TEMPDIR > /dev/null
|
|
|
|
# loop on the channel list
|
|
for channel in ${channel_list}; do
|
|
local_channel_img=${channel%:*}
|
|
local_channel_tag=${channel#*:}
|
|
|
|
log_info "Found channel image: ${local_channel_img}:${local_channel_tag}"
|
|
|
|
# extract the channel.json
|
|
if ! docker run --entrypoint busybox ${local_channel_img}:${local_channel_tag} cat channel.json > channel_${local_channel_img//\//_}_${local_channel_tag}.json; then
|
|
exit_error "cannot extract OS images"
|
|
fi
|
|
done
|
|
|
|
# Merge all channel_*.json files
|
|
if ! jq -s add channel_*.json > channel.json; then
|
|
exit_error "cannot merge channel json files"
|
|
fi
|
|
|
|
# write the new channel and identify OS images to save
|
|
local new_channel=""
|
|
local -i index=0
|
|
while true; do
|
|
local item item_type item_image item_name item_url_field
|
|
item=$(jq .[$index] channel.json)
|
|
[[ "$item" == "null" ]] && break
|
|
|
|
# increment index
|
|
index+=1
|
|
|
|
get_json_val item_name "$item" ".metadata.name"
|
|
get_json_val item_type "$item" ".spec.type"
|
|
get_json_val item_display "$item" ".spec.metadata.displayName"
|
|
|
|
# drop the items in the channel which are not containers
|
|
case $item_type in
|
|
container)
|
|
item_url_field=".spec.metadata.upgradeImage"
|
|
get_json_val item_image "$item" "$item_url_field"
|
|
;;
|
|
iso)
|
|
item_url_field=".spec.metadata.uri"
|
|
get_json_val item_image "$item" "$item_url_field"
|
|
case $item_image in
|
|
"http://"*|"https://"*)
|
|
log_debug "skip OS $item_type entry:\t$item_name\t$item_image"
|
|
continue
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
log_info "ERR: unknown image type `$item_type`, skip OS entry '$item_name'"
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
log_info "Extract OS image:\n\t$item_name ($item_display)\n\t$item_image"
|
|
|
|
if [[ "$SKIP_ARCHIVE_CREATION" != "true" ]]; then
|
|
# save the OS image
|
|
if is_hauler; then
|
|
if ! hauler_store_add_image "${item_image}" "neverquit"; then
|
|
continue
|
|
fi
|
|
elif ! pull_image "${item_image}"; then
|
|
continue
|
|
fi
|
|
fi
|
|
add_image_to_export_list "${item_image}"
|
|
|
|
# prepend the private registry name
|
|
set_json_val item "$item" "$item_url_field" "${LOCAL_REGISTRY}/${item_image}"
|
|
|
|
[[ -z "$new_channel" ]] && new_channel="[${item}" || new_channel="${new_channel},${item}"
|
|
done
|
|
new_channel="${new_channel}]"
|
|
|
|
local channel_full_url="${CHANNEL_IMAGE_NAME}:${channel_tag}"
|
|
is_hauler && channel_full_url=localhost:5000/${channel_full_url}
|
|
log_info "Create new channel image for the private registry: ${channel_full_url}"
|
|
jq -n "$new_channel" > channel.json
|
|
cat << EOF > Dockerfile
|
|
FROM registry.suse.com/bci/bci-busybox:latest
|
|
ADD channel.json /channel.json
|
|
USER 10010:10010
|
|
ENTRYPOINT ["busybox", "cp"]
|
|
CMD ["/channel.json", "/data/output"]
|
|
EOF
|
|
docker build . -t ${channel_full_url}
|
|
if is_hauler; then
|
|
hauler_start_local_registry
|
|
docker push ${channel_full_url}
|
|
hauler_store_add_image ${channel_full_url}
|
|
hauler_stop_local_registry
|
|
fi
|
|
|
|
popd > /dev/null
|
|
[[ "$DEBUG" == "false" ]] && rm -rf $TEMPDIR
|
|
|
|
add_image_to_export_list "${channel_full_url}"
|
|
}
|
|
|
|
hauler_start_local_registry() {
|
|
# hauler needs something in the store to start the registry
|
|
log_debug "start Hauler registry in $HAULER_REG_DIR"
|
|
pushd ${HAULER_REG_DIR} > /dev/null
|
|
touch ${HAULER_REG_DUMMY_FILE}
|
|
hauler store add file ${HAULER_REG_DUMMY_FILE}
|
|
hauler store serve registry > /dev/null 2>&1 &
|
|
if (( $? )); then
|
|
hauler_stop_local_registry
|
|
exit_error "hauler: cannot start registry"
|
|
fi
|
|
HAULER_REGISTRY_PID=$!
|
|
# wait the hauler registry to be up and running
|
|
sleep 1
|
|
popd > /dev/null
|
|
}
|
|
|
|
hauler_stop_local_registry() {
|
|
if [[ -n "{HAULER_REGISTRY_PID}" ]]; then
|
|
kill ${HAULER_REGISTRY_PID} > /dev/null 2>&1
|
|
fi
|
|
rm -rf ${HAULER_REG_DIR}
|
|
}
|
|
|
|
hauler_store_add_file() {
|
|
local file="$1"
|
|
local neverquit=${2:-""}
|
|
|
|
if ! hauler store -s ${HAULER_STORE} add file ${file}; then
|
|
# !hauler does not return error (yet): https://github.com/rancherfederal/hauler/issues/185
|
|
if [[ -z "$neverquit" ]]; then
|
|
exit_error "hauler: cannot add file ${file}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
hauler_store_add_image() {
|
|
local img="$1"
|
|
local neverquit=${2:-""}
|
|
|
|
if ! hauler store -s ${HAULER_STORE} add image ${img}; then
|
|
# !hauler does not return error (yet): https://github.com/rancherfederal/hauler/issues/185
|
|
if [[ -z "$neverquit" ]]; then
|
|
exit_error "hauler: cannot add image ${img}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
create_container_images_archive() {
|
|
if is_hauler; then
|
|
log_info "Creating haul ${CONTAINER_IMAGES_ARCHIVE}"
|
|
hauler store -s ${HAULER_STORE} save -f ${CONTAINER_IMAGES_ARCHIVE}
|
|
return 0
|
|
fi
|
|
|
|
echo -n "" > "${CONTAINER_IMAGES_FILE}"
|
|
for i in ${IMAGES_TO_SAVE} ; do
|
|
log_debug "* $i"
|
|
echo "$i" >> "${CONTAINER_IMAGES_FILE}"
|
|
done
|
|
sort -u ${CONTAINER_IMAGES_FILE} -o ${CONTAINER_IMAGES_FILE}
|
|
|
|
[[ "$SKIP_ARCHIVE_CREATION" == "true" ]] && return 0
|
|
|
|
log_info "Creating ${CONTAINER_IMAGES_ARCHIVE} with $(echo ${IMAGES_TO_SAVE} | wc -w | tr -d '[:space:]') images (may take a while)"
|
|
docker save $(echo ${IMAGES_TO_SAVE}) | gzip --stdout > ${CONTAINER_IMAGES_ARCHIVE}
|
|
}
|
|
|
|
print_next_steps() {
|
|
local registry_url
|
|
|
|
[[ "$SKIP_ARCHIVE_CREATION" == "true" ]] && return 0
|
|
|
|
get_chart_val registry_url "registryUrl"
|
|
|
|
if is_hauler; then
|
|
print_next_steps_hauler
|
|
else
|
|
print_next_steps_docker
|
|
fi
|
|
}
|
|
|
|
print_next_steps_docker() {
|
|
cat <<- EOF
|
|
|
|
|
|
NEXT STEPS:
|
|
|
|
1) Load the '$CONTAINER_IMAGES_ARCHIVE' to the local registry ($LOCAL_REGISTRY)
|
|
available in the airgapped infrastructure:
|
|
|
|
./rancher-load-images.sh \\
|
|
--image-list $CONTAINER_IMAGES_FILE \\
|
|
--images $CONTAINER_IMAGES_ARCHIVE \\
|
|
--registry $LOCAL_REGISTRY
|
|
|
|
2) Install the elemental charts downloaded in the current directory passing the local registry
|
|
and the newly created channel image:
|
|
|
|
helm upgrade --create-namespace -n cattle-elemental-system --install elemental-operator-crds $CHART_NAME_CRDS
|
|
|
|
helm upgrade --create-namespace -n cattle-elemental-system --install elemental-operator $CHART_NAME_OPERATOR \\
|
|
--set registryUrl=$LOCAL_REGISTRY \\
|
|
--set $CHANNEL_IMAGE_VAR=$CHANNEL_IMAGE_VAL
|
|
EOF
|
|
}
|
|
|
|
print_next_steps_hauler() {
|
|
cat <<- EOF
|
|
|
|
|
|
NEXT STEPS:
|
|
|
|
1) Load the '$CONTAINER_IMAGES_ARCHIVE' Haul archive in the Hauler instance in the airgapped infrastructure:
|
|
|
|
hauler store load '$CONTAINER_IMAGES_ARCHIVE'
|
|
|
|
2) If the local registry is not served by Hauler, copy the content of the Haul archive to the local registry:
|
|
|
|
hauler store copy registry://$LOCAL_REGISTRY
|
|
|
|
for more options and information on Hauler, check the official docs:
|
|
https://rancherfederal.github.io/hauler-docs/
|
|
|
|
3) Extract the elemental charts from the Hauler store in the airgapped infrastructure:
|
|
|
|
hauler store extract $CHART_NAME_CRDS
|
|
|
|
hauler store extract $CHART_NAME_OPERATOR
|
|
|
|
and install them passing the local registry and the newly created channel image:
|
|
|
|
helm upgrade --create-namespace -n cattle-elemental-system --install elemental-operator-crds $CHART_NAME_CRDS
|
|
|
|
helm upgrade --create-namespace -n cattle-elemental-system --install elemental-operator $CHART_NAME_OPERATOR \\
|
|
--set registryUrl=$LOCAL_REGISTRY \\
|
|
--set $CHANNEL_IMAGE_VAR=$CHANNEL_IMAGE_VAL
|
|
EOF
|
|
}
|
|
|
|
clean_up() {
|
|
is_hauler || return 0
|
|
|
|
# only hauler stuffs need to be cleaned at the end
|
|
[[ "$DEBUG" == "false" ]] && \
|
|
rm -rf ${HAULER_STORE} ${CHART_NAME_CRDS} ${CHART_NAME_OPERATOR}
|
|
}
|
|
|
|
parse_parameters "$@"
|
|
|
|
prereq_checks
|
|
|
|
fetch_charts
|
|
|
|
pull_chart_container_images
|
|
|
|
build_os_channel
|
|
|
|
create_container_images_archive
|
|
|
|
print_next_steps
|
|
|
|
clean_up
|