Skip to content

Instantly share code, notes, and snippets.

@jakefhyde
Last active January 3, 2024 20:30
Show Gist options
  • Select an option

  • Save jakefhyde/8646915941fa84a942397df5fb3ed1c8 to your computer and use it in GitHub Desktop.

Select an option

Save jakefhyde/8646915941fa84a942397df5fb3ed1c8 to your computer and use it in GitHub Desktop.
Runs an ssh command on all nodes in a rancher v2prov cluster
#!/bin/bash
#
# Given a command, rancher server url, rancher admin token, namespace and name of a v2prov cluster:
# 1. Get the management cluster name
# 2. Download the kubeconfig
# 3. Get the list of CAPI machines
# 4. For each CAPI machine:
# a. Download the ssh keys to a temp directory
# b. Get the IP address of the node
# b. Run a command on the node via ssh
set -e
function display_help() {
echo "Usage: $(basename $0) --source [source tag] --dest [dest tag]"
echo
echo ' $RANCHER_TOKEN [Required] environment variable containing rancher admin token'
echo ' -s, --server-url [Required] rancher server url'
echo " -c, --cluster [Required] target cluster name (provisioning.cattle.io)"
echo " -r, --run-command [Required] ssh command to run on the nodes"
echo " -n, --namespace [Optional] namespace cluster & machines live in (default: fleet-default)"
echo " -l, --label-selector [Optional] selector to use to filter machines"
echo " -d, --debug [Optional] calls 'set -x'"
echo " -h, --help print this message"
}
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-s|--server-url)
SERVER_URL="$2"
shift # past argument
shift # past value
;;
-c|--cluster)
CLUSTER="$2"
shift # past argument
shift # past value
;;
-n|--namespace)
NAMESPACE="$2"
shift # past argument
shift # past value
;;
-l|--label-selector)
LABEL_SELECTOR="$2"
shift # past argument
shift # past value
;;
-r|--run-command)
RUN_COMMAND="$2"
shift # past argument
shift # past value
;;
-d|--debug)
set -x
shift # past argument
;;
-h|--help)
display_help
exit 1
;;
-*|--*)
echo "Unknown option $1"
display_help
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [[ -z "$RANCHER_TOKEN" ]]; then
echo '$RANCHER_TOKEN is unset'
display_help
exit 1
fi
if [[ -z "$SERVER_URL" ]]; then
echo '--server-url is unset'
display_help
exit 1
fi
if [[ -z "$CLUSTER" ]]; then
echo '--cluster is unset'
display_help
exit 1
fi
if [[ -z "$RUN_COMMAND" ]]; then
echo '--run-command is unset'
display_help
exit 1
fi
NAMESPACE=${NAMESPACE:-fleet-default}
runCommand() {
local machineName
machineName="$1"
local runCmd
runCmd="$2"
local nodeName
nodeName="$(kubectl get machine -n "${NAMESPACE}" "$machineName" -o json | jq -r '.status.nodeRef.name')"
local ip
ip="$(kubectl get machine -n "${NAMESPACE}" "$machineName" -o json | jq -r '.status.addresses[0].address')"
echo "Running command '${RUN_COMMAND}' on machine '$machineName' with address '$ip'"
ssh -o "StrictHostKeyChecking no" -i "./${nodeName}/id_rsa" "root@$ip" "${runCmd}"
}
downloadKeys() {
local machineName
machineName="$1"
echo "Downloading ssh key for machine '$machineName'"
curl "https://${SERVER_URL}/v1/cluster.x-k8s.io.machines/${NAMESPACE}/${machineName}/sshkeys" \
-s \
-H "cookie: R_SESS=${RANCHER_TOKEN}" \
--compressed \
-o "${machineName}.zip"
unzip "${machineName}.zip" > /dev/null
rm "${machineName}.zip"
}
getAllMachines() {
echo "Getting local cluster CAPI machines belonging to cluster '$CLUSTER'"
if [[ -n $LABEL_SELECTOR ]]; then
LABEL_SELECTOR="cluster.x-k8s.io/cluster-name=${CLUSTER},${LABEL_SELECTOR}"
else
LABEL_SELECTOR="cluster.x-k8s.io/cluster-name=${CLUSTER}"
fi
MACHINES=$(kubectl --kubeconfig .kube/config get machines -n "${NAMESPACE}" -l "${LABEL_SELECTOR}" -o jsonpath='{.items[*].metadata.name}')
}
# Unused, but useful
getKubeConfig() {
curl "https://${SERVER_URL}/v3/clusters/${MANAGEMENT_CLUSTER_NAME}?action=generateKubeconfig" \
-X 'POST' \
-H 'accept: application/yaml' \
-H "cookie: R_SESS=${RANCHER_TOKEN}" \
--compressed | yq -r '.config' > .kube/config
}
getLocalKubeConfig() {
echo "Getting local cluster kubeconfig"
curl "https://${SERVER_URL}/v3/clusters/local?action=generateKubeconfig" \
-X 'POST' \
-H 'accept: application/yaml' \
-H "cookie: R_SESS=${RANCHER_TOKEN}" \
--compressed | yq -r '.config' > .kube/config
}
getManagementClusterName() {
echo "Getting name of management cluster"
MANAGEMENT_CLUSTER_NAME=$(curl "https://${SERVER_URL}/v1/provisioning.cattle.io.cluster/${NAMESPACE}/${CLUSTER}" \
-H 'accept: application/json' \
-H "cookie: R_SESS=${RANCHER_TOKEN}" \
--compressed | jq -r '.status.clusterName')
}
main() {
cd "$(mktemp -d)"
mkdir -p .kube
getManagementClusterName
getLocalKubeConfig
getAllMachines
for machine in $MACHINES; do
downloadKeys "$machine"
runCommand "$machine" "$RUN_COMMAND"
done
}
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment