277 lines
6.8 KiB
Bash
Executable File
277 lines
6.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Copyright 2022 The Karmada Authors.
|
|
#
|
|
# 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.
|
|
|
|
set -o errexit
|
|
set -o nounset
|
|
set -o pipefail
|
|
|
|
# This script installs karmada cli tools to the install location you want.
|
|
# Usage: ./install-cli.sh <install_cli_type>
|
|
# Example:
|
|
|
|
# ./install-cli.sh
|
|
# will install the latest karmadactl to /usr/local/bin
|
|
|
|
# ./install-cli.sh kubectl-karmada
|
|
# will install the latest kubectl-karmada to /usr/local/bin
|
|
|
|
# export INSTALL_CLI_VERSION=1.3.0
|
|
# ./install-cli.sh
|
|
# will install the 1.3.0 karmadactl to /usr/local/bin
|
|
|
|
# INSTALL_CLI_TYPE supports 'karmadactl' or 'kubectl-karmada'.
|
|
INSTALL_CLI_TYPE=${1:-"karmadactl"}
|
|
# INSTALL_CLI_VERSION represents which version should be installed.
|
|
# Defaults to 'latest' means latest release version.
|
|
INSTALL_CLI_VERSION=${INSTALL_CLI_VERSION:-"latest"}
|
|
# INSTALL_LOCATION represents where to put the CLI.
|
|
INSTALL_LOCATION=${INSTALL_LOCATION:-"/usr/local/bin"}
|
|
GITHUB_REPO="karmada-io/karmada"
|
|
|
|
# Helper functions for logs
|
|
info() {
|
|
echo '[INFO] ' "$@"
|
|
}
|
|
|
|
warn() {
|
|
echo '[WARN] ' "$@" >&2
|
|
}
|
|
|
|
fatal() {
|
|
echo '[ERROR] ' "$@" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Set os, fatal if operating system not supported
|
|
setup_verify_os() {
|
|
if [[ -z "${OS-}" ]]; then
|
|
OS=$(uname)
|
|
fi
|
|
case ${OS} in
|
|
Darwin)
|
|
OS=darwin
|
|
;;
|
|
Linux)
|
|
OS=linux
|
|
;;
|
|
*)
|
|
fatal "Unsupported operating system ${OS}"
|
|
esac
|
|
}
|
|
|
|
# Set arch, fatal if architecture not supported
|
|
setup_verify_arch() {
|
|
if [[ -z "${ARCH-}" ]]; then
|
|
ARCH=$(uname -m)
|
|
fi
|
|
case ${ARCH} in
|
|
arm64|aarch64|armv8l)
|
|
ARCH=arm64
|
|
;;
|
|
amd64|x86_64)
|
|
ARCH=amd64
|
|
;;
|
|
*)
|
|
fatal "Unsupported architecture ${ARCH}"
|
|
esac
|
|
}
|
|
|
|
# Set cli tools, install karmadactl by default, fatal if cli tool not supported
|
|
setup_install_cli() {
|
|
case ${INSTALL_CLI_TYPE} in
|
|
karmadactl|kubectl-karmada)
|
|
;;
|
|
*)
|
|
fatal "Unsupported cli tool ${INSTALL_CLI_TYPE}"
|
|
esac
|
|
}
|
|
|
|
# Verify existence of downloader executable
|
|
verify_downloader() {
|
|
# Return failure if it doesn't exist or is no executable
|
|
[[ -x "$(which "$1")" ]] || return 1
|
|
|
|
# Set verified executable as our downloader program and return success
|
|
DOWNLOADER=$1
|
|
return 0
|
|
}
|
|
|
|
# Create temporary directory and cleanup when done
|
|
setup_tmp() {
|
|
TMP_DIR=$(mktemp -d -t "${INSTALL_CLI_TYPE}"-install.XXXXXXXXXX)
|
|
TMP_METADATA="${TMP_DIR}/${INSTALL_CLI_TYPE}.json"
|
|
TMP_HASH="${TMP_DIR}/${INSTALL_CLI_TYPE}.hash"
|
|
TMP_BIN="${TMP_DIR}/${INSTALL_CLI_TYPE}.tgz"
|
|
cleanup() {
|
|
local code=$?
|
|
rm -rf "${TMP_DIR}" || true
|
|
exit ${code}
|
|
}
|
|
trap cleanup INT EXIT
|
|
}
|
|
|
|
# Find version from Github metadata
|
|
get_release_version() {
|
|
if [[ "${INSTALL_CLI_VERSION-}" != "latest" ]]; then
|
|
SUFFIX_URL="tags/v${INSTALL_CLI_VERSION}"
|
|
else
|
|
SUFFIX_URL="latest"
|
|
fi
|
|
|
|
METADATA_URL="https://api.github.com/repos/${GITHUB_REPO}/releases/${SUFFIX_URL}"
|
|
|
|
info "Downloading metadata ${METADATA_URL}"
|
|
download "${TMP_METADATA}" "${METADATA_URL}"
|
|
|
|
VERSION_KARMADA=$(grep '"tag_name":' "${TMP_METADATA}" | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
|
|
if [[ -n "${VERSION_KARMADA}" ]]; then
|
|
info "Using ${VERSION_KARMADA} as release"
|
|
else
|
|
fatal "Unable to determine release version"
|
|
fi
|
|
|
|
ret=0
|
|
vercomp ${VERSION_KARMADA} 1.2.0 || ret=$?
|
|
if [[ $ret -eq 2 ]]; then
|
|
fatal "Installation of cli tools before version 1.2.0 is not supported"
|
|
fi
|
|
}
|
|
|
|
# Download from file from URL
|
|
download() {
|
|
[[ $# -eq 2 ]] || fatal 'download needs exactly 2 arguments'
|
|
|
|
ret=0
|
|
case $DOWNLOADER in
|
|
curl)
|
|
curl -o "$1" -sfL "$2" || ret=$?
|
|
;;
|
|
wget)
|
|
wget -qO "$1" "$2" || ret=$?
|
|
;;
|
|
*)
|
|
fatal "Incorrect executable '${DOWNLOADER}'"
|
|
;;
|
|
esac
|
|
|
|
# Abort if download command failed
|
|
[[ $ret -eq 0 ]] || fatal 'Download failed'
|
|
}
|
|
|
|
# Version comparison
|
|
# Returns 0 on '=', 1 on '>', and 2 on '<'.
|
|
# Ref: https://stackoverflow.com/a/4025065
|
|
vercomp () {
|
|
if [[ $1 == $2 ]]
|
|
then
|
|
return 0
|
|
fi
|
|
local IFS=.
|
|
local i ver1=($1) ver2=($2)
|
|
# fill empty fields in ver1 with zeros
|
|
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
|
|
do
|
|
ver1[i]=0
|
|
done
|
|
for ((i=0; i<${#ver1[@]}; i++))
|
|
do
|
|
if [[ -z ${ver2[i]} ]]
|
|
then
|
|
# fill empty fields in ver2 with zeros
|
|
ver2[i]=0
|
|
fi
|
|
if ((10#${ver1[i]} > 10#${ver2[i]}))
|
|
then
|
|
return 1
|
|
fi
|
|
if ((10#${ver1[i]} < 10#${ver2[i]}))
|
|
then
|
|
return 2
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
# Download hash from Github URL
|
|
download_hash() {
|
|
HASH_URL="https://github.com/${GITHUB_REPO}/releases/download/v${VERSION_KARMADA}/${INSTALL_CLI_TYPE}-${OS}-${ARCH}.tgz.sha256"
|
|
|
|
info "Downloading hash ${HASH_URL}"
|
|
download "${TMP_HASH}" "${HASH_URL}"
|
|
HASH_EXPECTED=$(grep "${INSTALL_CLI_TYPE}-${OS}-${ARCH}.tgz" "${TMP_HASH}")
|
|
HASH_EXPECTED=${HASH_EXPECTED%%[[:blank:]]*}
|
|
}
|
|
|
|
# Download binary from Github URL
|
|
download_binary() {
|
|
BIN_URL="https://github.com/${GITHUB_REPO}/releases/download/v${VERSION_KARMADA}/${INSTALL_CLI_TYPE}-${OS}-${ARCH}.tgz"
|
|
info "Downloading binary ${BIN_URL}"
|
|
download "${TMP_BIN}" "${BIN_URL}"
|
|
}
|
|
|
|
compute_sha256sum() {
|
|
cmd=$(which sha256sum shasum | head -n 1)
|
|
case $(basename "$cmd") in
|
|
sha256sum)
|
|
sha256sum "$1" | cut -f 1 -d ' '
|
|
;;
|
|
shasum)
|
|
shasum -a 256 "$1" | cut -f 1 -d ' '
|
|
;;
|
|
*)
|
|
fatal "Can not find sha256sum or shasum to compute checksum"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Verify downloaded binary hash
|
|
verify_binary() {
|
|
info "Verifying binary download"
|
|
HASH_BIN=$(compute_sha256sum "${TMP_BIN}")
|
|
HASH_BIN=${HASH_BIN%%[[:blank:]]*}
|
|
if [[ "${HASH_EXPECTED}" != "${HASH_BIN}" ]]; then
|
|
fatal "Download sha256 does not match ${HASH_EXPECTED}, got ${HASH_BIN}"
|
|
fi
|
|
}
|
|
|
|
# Setup permissions and move binary
|
|
setup_binary() {
|
|
info "Installing ${INSTALL_CLI_TYPE} to ${INSTALL_LOCATION}/${INSTALL_CLI_TYPE}"
|
|
tar -xzof "${TMP_BIN}" -C "${TMP_DIR}" --no-same-owner
|
|
|
|
mkdir -p "${INSTALL_LOCATION}" &>/dev/null || sudo mkdir -p "${INSTALL_LOCATION}"
|
|
|
|
local CMD_MOVE="mv -i \"${TMP_DIR}/${INSTALL_CLI_TYPE}\" \"${INSTALL_LOCATION}\""
|
|
if [[ -w "${INSTALL_LOCATION}" ]]; then
|
|
eval "${CMD_MOVE} < /dev/tty"
|
|
else
|
|
eval "sudo ${CMD_MOVE} < /dev/tty"
|
|
fi
|
|
}
|
|
|
|
# Run the install process
|
|
{
|
|
setup_verify_os
|
|
setup_verify_arch
|
|
setup_install_cli
|
|
verify_downloader curl || verify_downloader wget || fatal 'Can not find curl or wget for downloading files'
|
|
setup_tmp
|
|
get_release_version
|
|
download_hash
|
|
download_binary
|
|
verify_binary
|
|
setup_binary
|
|
}
|