Skip to content

External variables and verbosity #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e9948f1
Fixed issues
May 15, 2025
9d5a4d0
Fixed issues
May 15, 2025
a996635
Made scripts a bit more verbose, added support for Ubuntu in bootstra…
May 15, 2025
e08a772
Added Linux Support in Bootstrap Script
May 16, 2025
eb0e819
Merge branch 'main' of https://github.com/SovereignCloudStack/scs-tra…
May 16, 2025
d9debc6
Adjusted .gitignore to allow for cert-sample-files
May 16, 2025
b4885ef
Adjusted cluster-settings.env.sample to contain a feasible configuration
May 16, 2025
ca2031b
Merge branch 'main' of https://github.com/SovereignCloudStack/scs-tra…
May 17, 2025
6607e68
Merge branch 'main' into external_variables_and_verbosity
May 17, 2025
ffec870
Make CCM load balancer type configurable and simplify cluster wait sc…
May 17, 2025
1680437
Removed Claude.md file
ksamaschke May 17, 2025
81d2227
Remove CLAUDE.md from version control
May 17, 2025
5953ff6
Merge branch 'external_variables_and_verbosity' of https://github.com…
May 17, 2025
dff7a43
Add config preparation utility and remove obsolete timeout parameter
May 17, 2025
6506fbe
Merge branch 'main' into external_variables_and_verbosity
garloff May 20, 2025
2015108
Merge branch 'main' into external_variables_and_verbosity
garloff May 21, 2025
75a97ad
Put auth section at the end, use test domain.
garloff May 21, 2025
01be45d
Streamline variable naming. Use LBTYPE and WORKERCLASS.
garloff May 21, 2025
ee85693
Merge branch 'main' into external_variables_and_verbosity
garloff May 23, 2025
1e72f93
Merge branch 'main' into external_variables_and_verbosity
garloff May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
**/.claude/settings.local.json

# Claude's instructions file
CLAUDE.md

# Certificate files
*.cert

# Environment files
cluster-settings.env
clouds.yaml
211 changes: 171 additions & 40 deletions 00-bootstrap-vm-cs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,209 @@
# (c) Kurt Garloff <s7n@garloff.de>, 2/2025
# SPDX-License-Identifier: CC-BY-SA-4.0

# ToDo: Magic to switch b/w apt, zypper, dnf, pacman, ...
# Detect architecture and OS
ARCH=$(uname -m)
ARCH="${ARCH/x86_64/amd64}"
OS=$(uname -s | tr A-Z a-z)

# Detect distribution details from os-release
if [ -f /etc/os-release ]; then
# Load variables from os-release file
. /etc/os-release
OS_ID=$ID
OS_VERSION_ID=$VERSION_ID
OS_ID_LIKE=$ID_LIKE
else
# Fallback to basic detection
OS_ID="unknown"
OS_VERSION_ID="unknown"
OS_ID_LIKE=""
fi

echo "Detected OS: $OS_ID $OS_VERSION_ID"

# Usage: install_via_pkgmgr pkgnm [pkgnm [...]]
install_via_pkgmgr()
{
sudo $INSTCMD "$@"
echo "Installing packages: $@"
sudo $INSTCMD "$@" || { echo "Failed to install packages: $@"; return 1; }
echo "Successfully installed packages: $@"
}

# Verify sha256sum
test_sha256()
{
OUT=$(sha256sum "$1")
OUT=${OUT%% *}
if test "$OUT" != "$2"; then return 1; else return 0; fi
OUT=$(sha256sum "$1")
OUT=${OUT%% *}
if test "$OUT" != "$2"; then
echo "ERROR: Checksum mismatch for ${1}" 1>&2
echo "Expected: $2" 1>&2
echo "Got: $OUT" 1>&2
return 1
else
echo "Checksum verified for ${1}"
return 0
fi
}

# Usage install_via_download_bin URL sha256 [newname]
install_via_download_bin()
{
cd ~/Download
curl -LO "$1" || return
FNM="${1##*/}"
if ! test_sha256 "$FNM" "$2"; then echo "Checksum mismatch for ${FNM}" 1>&2; return 1; fi
chmod +x "$FNM"
sudo mv "$FNM" /usr/local/bin/"$3"
cd ~/Download || { echo "ERROR: Failed to cd into ~/Download"; return 1; }
echo "Downloading $1..."
curl -LO "$1" || { echo "ERROR: Failed to download $1"; return 1; }
FNM="${1##*/}"
if ! test_sha256 "$FNM" "$2"; then return 1; fi
chmod +x "$FNM" || { echo "ERROR: Failed to set executable permissions on $FNM"; return 1; }

# Determine target filename
local TARGET="/usr/local/bin/${FNM}"
if [ -n "$3" ] && [ "$3" != "." ]; then
TARGET="/usr/local/bin/$3"
fi

echo "Moving $FNM to $TARGET"
sudo mv "$FNM" "$TARGET" || { echo "ERROR: Failed to move $FNM to $TARGET"; return 1; }
echo "Successfully installed $TARGET"
}

# Usage install_via_download_bin URL sha256 extrpath [newname]
# Usage install_via_download_tgz URL sha256 extrpath [newname]
install_via_download_tgz()
{
cd ~/Download
curl -LO "$1" || return
FNM="${1##*/}"
if ! test_sha256 "$FNM" "$2"; then echo "Checksum mismatch for ${FNM}" 1>&2; return 1; fi
tar xvzf "$FNM"
sudo mv "$3" /usr/local/bin/"$4"
cd ~/Download || { echo "ERROR: Failed to cd into ~/Download"; return 1; }
echo "Downloading $1..."
curl -LO "$1" || { echo "ERROR: Failed to download $1"; return 1; }
FNM="${1##*/}"
if ! test_sha256 "$FNM" "$2"; then return 1; fi

echo "Extracting $FNM..."
tar xzf "$FNM" || { echo "ERROR: Failed to extract $FNM"; return 1; }

# Determine target filename
local TARGET="/usr/local/bin/${3##*/}"
if [ -n "$4" ] && [ "$4" != "." ]; then
TARGET="/usr/local/bin/$4"
fi

echo "Moving $3 to $TARGET"
sudo mv "$3" "$TARGET" || {
echo "ERROR: Failed to move $3 to $TARGET";
echo "Looking for file to move...";
find . -name "${3##*/}" -type f;
return 1;
}
echo "Successfully installed $TARGET"
}

# Debian 12 (Bookworm)
# Ensure the Download directory exists and is writable
echo "Creating Download directory if needed..."
mkdir -p ~/Download
if [ ! -d ~/Download ]; then
echo "ERROR: Could not create ~/Download directory"
exit 1
fi
# Make sure we have write permissions
touch ~/Download/.write_test && rm ~/Download/.write_test || {
echo "ERROR: Cannot write to ~/Download directory"
exit 1
}

# Set up package manager command
INSTCMD="apt-get install -y --no-install-recommends --no-install-suggests"
DEB12_PKGS=(docker.io golang jq yq git gh python3-openstackclient)
DEB12_TGZS=("https://get.helm.sh/helm-v3.17.1-${OS}-${ARCH}.tar.gz")
DEB12_TCHK=("3b66f3cd28409f29832b1b35b43d9922959a32d795003149707fea84cbcd4469")
DEB12_TOLD=("${OS}-${ARCH}/helm")
DEB12_TNEW=(".")
DEB12_BINS=("https://github.com/kubernetes-sigs/kind/releases/download/v0.26.0/kind-${OS}-${ARCH}"
"https://dl.k8s.io/release/v1.31.6/bin/${OS}/${ARCH}/kubectl"
"https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.9.4/clusterctl-${OS}-${ARCH}"
)
DEB12_BCHK=("d445b44c28297bc23fd67e51cc24bb294ae7b977712be2d4d312883d0835829b"
"c46b2f5b0027e919299d1eca073ebf13a4c5c0528dd854fc71a5b93396c9fa9d"
"0c80a58f6158cd76075fcc9a5d860978720fa88860c2608bb00944f6af1e5752"
)
DEB12_BNEW=("kind" "." "clusterctl")

# Define package list with conditional logic for Docker based on distribution
if [ "$OS_ID" = "ubuntu" ]; then
echo "Setting up Docker repository for Ubuntu..."
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$OS_ID $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
PACKAGES=(docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin golang jq git gh python3-openstackclient)
elif [ "$OS_ID" = "debian" ] || [[ "$OS_ID_LIKE" == *"debian"* ]]; then
echo "Using Debian package sources..."
PACKAGES=(docker.io golang jq git gh python3-openstackclient)
else
echo "Using default package list for unknown distribution..."
PACKAGES=(docker.io golang jq git gh python3-openstackclient)
fi

# Define binary downloads with their checksums
TARBALLS=("https://get.helm.sh/helm-v3.17.1-${OS}-${ARCH}.tar.gz")
TARBALL_CHECKSUMS=("3b66f3cd28409f29832b1b35b43d9922959a32d795003149707fea84cbcd4469")
TARBALL_EXTRACT_PATHS=("${OS}-${ARCH}/helm")
TARBALL_NEW_NAMES=(".")

BINARIES=("https://github.com/kubernetes-sigs/kind/releases/download/v0.26.0/kind-${OS}-${ARCH}"
"https://dl.k8s.io/release/v1.31.6/bin/${OS}/${ARCH}/kubectl"
"https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.9.4/clusterctl-${OS}-${ARCH}")
BINARY_CHECKSUMS=("d445b44c28297bc23fd67e51cc24bb294ae7b977712be2d4d312883d0835829b"
"c46b2f5b0027e919299d1eca073ebf13a4c5c0528dd854fc71a5b93396c9fa9d"
"0c80a58f6158cd76075fcc9a5d860978720fa88860c2608bb00944f6af1e5752")
BINARY_NEW_NAMES=("kind" "." "clusterctl")

# Update package lists
echo "Updating package lists..."
sudo apt-get update
install_via_pkgmgr "${DEB12_PKGS[@]}" || exit 1
for i in $(seq 0 $((${#DEB12_TGZS[*]}-1))); do
install_via_download_tgz "${DEB12_TGZS[$i]}" "${DEB12_TCHK[$i]}" "${DEB12_TOLD[$i]}" "${DEB12_TNEW[$i]}" || exit 2

# Install packages
echo "Installing required packages..."
install_via_pkgmgr "${PACKAGES[@]}" || exit 1

# Install tools from tarballs
echo "Installing tools from tarballs..."
for i in $(seq 0 $((${#TARBALLS[*]}-1))); do
echo "Processing tarball ${TARBALLS[$i]}..."
install_via_download_tgz "${TARBALLS[$i]}" "${TARBALL_CHECKSUMS[$i]}" "${TARBALL_EXTRACT_PATHS[$i]}" "${TARBALL_NEW_NAMES[$i]}" || exit 2
done
for i in $(seq 0 $((${#DEB12_BINS[*]}-1))); do
install_via_download_bin "${DEB12_BINS[$i]}" "${DEB12_BCHK[$i]}" "${DEB12_BNEW[$i]}" || exit 3

# Install binary tools
echo "Installing binary tools..."
for i in $(seq 0 $((${#BINARIES[*]}-1))); do
echo "Processing binary ${BINARIES[$i]}..."
install_via_download_bin "${BINARIES[$i]}" "${BINARY_CHECKSUMS[$i]}" "${BINARY_NEW_NAMES[$i]}" || exit 3
done

# Install envsubst
echo "Installing envsubst..."
GOBIN=/tmp go install github.com/drone/envsubst/v2/cmd/envsubst@latest
sudo mv /tmp/envsubst /usr/local/bin/

test -e "~/.bash_aliases" || echo -e "alias ll='ls -lF'\nalias k=kubectl" > ~/.bash_aliases
sudo groupmod -a -U `whoami` docker
# Set up bash aliases if they don't exist
echo "Setting up bash aliases..."
if [ ! -e ~/.bash_aliases ]; then
echo -e "alias ll='ls -lF'\nalias k=kubectl" > ~/.bash_aliases
echo "Created ~/.bash_aliases file"
fi

# Set up Docker group
echo "Adding current user to Docker group..."
# First check if docker group exists
if getent group docker > /dev/null; then
# Add user to docker group - different syntax for Ubuntu vs Debian
if [ "$OS_ID" = "ubuntu" ]; then
echo "Using Ubuntu-specific command to add user to docker group..."
sudo usermod -aG docker $(whoami)
else
echo "Using Debian-specific command to add user to docker group..."
sudo groupmod -a -U $(whoami) docker
fi
echo "User $(whoami) added to docker group"
else
echo "Docker group does not exist. Creating docker group first..."
sudo groupadd docker
echo "Adding user $(whoami) to docker group..."
sudo usermod -aG docker $(whoami)
echo "User $(whoami) added to docker group"
fi

echo "Note: You may need to log out and back in for group changes to take effect"

# Start Docker
echo "Enabling and starting Docker service..."
sudo systemctl enable --now docker

echo "Installation complete! You may need to log out and back in for group changes to take effect."

7 changes: 7 additions & 0 deletions 01-kind-cluster.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash
# Create a local kind (Kubernetes in Docker) cluster
set -e

# Detect MTU of interface with default route
DEV=$(ip route show default | head -n1 | sed 's/^.*dev \([^ ]*\).*$/\1/')
CLOUDMTU=$(ip link show $DEV | head -n1 | sed 's/^.*mtu \([0-9]*\) .*$/\1/')
Expand All @@ -11,10 +13,15 @@ if test $DOCKERMTU -gt $CLOUDMTU; then
# Just in case ...
sudo sysctl net.ipv4.tcp_mtu_probing=1
fi

# Create kind cluster
if test "$(kind get clusters)" != "kind"; then
echo "Creating a new kind cluster..."
kind create cluster
else
echo "kind cluster already running"
fi

echo "Verifying cluster status..."
kubectl cluster-info
echo "Kind cluster ready."
19 changes: 16 additions & 3 deletions 02-deploy-capi.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
#!/bin/bash
# Rollout ORC, CAPI, CAPO
# Rollout ORC, CAPI, CAPO (Cluster API with OpenStack provider)
set -e
# Set feature flags

echo "Setting required feature flags for Cluster API..."
export CLUSTER_TOPOLOGY=true
export EXP_CLUSTER_RESOURCE_SET=true
export EXP_RUNTIME_SDK=true
echo "CLUSTER_TOPOLOGY=$CLUSTER_TOPOLOGY"
echo "EXP_CLUSTER_RESOURCE_SET=$EXP_CLUSTER_RESOURCE_SET"
echo "EXP_RUNTIME_SDK=$EXP_RUNTIME_SDK"

echo "Deploying OpenStack Resource Controller (ORC)..."
# We need ORC these days and clusterctl has chosen to ignore that
kubectl apply -f https://github.com/k-orc/openstack-resource-controller/releases/latest/download/install.yaml

echo "Initializing Cluster API with OpenStack infrastructure provider..."
# Rollout capi and capo (assuming that orc gets deployed independently)
clusterctl init --infrastructure openstack
# Wait for completion

echo "Waiting for CAPI deployments to be ready..."
kubectl -n capi-system rollout status deployment

echo "Waiting for CAPO deployments to be ready..."
kubectl -n capo-system rollout status deployment

echo "Cluster API components deployed successfully."

13 changes: 10 additions & 3 deletions 03-deploy-cso.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#!/bin/bash
# Deploy CSO
# Deploy Cluster Stack Operator (CSO)
set -e

echo "Creating temporary directory..."
mkdir ~/tmp || true

echo "Generating CSO RBAC configuration..."
cat > ~/tmp/cso-rbac.yaml <<EOF
clusterStackVariables:
ociRepository: registry.scs.community/kaas/cluster-stacks
Expand All @@ -22,8 +25,12 @@ controllerManager:
- update
- watch
EOF
# Install Cluster Stack Operator (CSO) with above values

echo "Installing Cluster Stack Operator with Helm..."
echo "Using registry.scs.community/kaas/cluster-stacks as OCI repository"
helm upgrade -i cso -n cso-system \
--create-namespace --values ~/tmp/cso-rbac.yaml \
oci://registry.scs.community/cluster-stacks/cso
kubectl -n cso-system rollout status deployment

echo "Waiting for CSO deployments to be ready..."
kubectl -n cso-system rollout status deployment
12 changes: 9 additions & 3 deletions 04-cloud-secret.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Create cloud secret
# Create cloud secret for OpenStack credentials
set -e
# We need settings
if test -n "$1"; then
Expand All @@ -11,15 +11,20 @@ else
fi
# Read settings -- make sure you can trust it
source "$SET"
echo "# Using settings from $SET"

# Read helper
THISDIR=$(dirname 0)
source "$THISDIR/yaml_parse.sh"

# Create namespace
test -n "$CS_NAMESPACE"
echo "Creating namespace $CS_NAMESPACE..."
kubectl create namespace "$CS_NAMESPACE" || true

# Default clouds.yaml location
CLOUDS_YAML=${CLOUDS_YAML:-~/.config/openstack/clouds.yaml}

# Use csp helper chart to create cloud secret
# Notes on expected clouds.yaml:
# - It should have the secrets (which you often keep in secure.yaml instead) merged into it
Expand Down Expand Up @@ -65,8 +70,7 @@ umask 0177
INJECTSUB="$SECRETS" INJECTSUBKWD="auth" RMVCOMMENT=1 REMOVE=cacert extract_yaml clouds.$OS_CLOUD < $CLOUDS_YAML | sed "s/^\\(\\s*\\)\\($OS_CLOUD\\):/\\1openstack:/" > ~/tmp/clouds-$OS_CLOUD.yaml
umask $OLD_UMASK
# FIXME: We will provide more settings in cluster-settings.env later, hardcode it for now
#if test "$CS_CCMLB=octavia-ovn"; then OCTOVN="--set octavia_ovn=true"; else unset OCTOVN; fi
OCTOVN="--set octavia_ovn=true"
if test "$CS_CCMLB" = "octavia-ovn"; then OCTOVN="--set octavia_ovn=true"; else unset OCTOVN; fi
if test -n "$OS_CACERT"; then
echo "# Found CA cert file configured to be \"$OS_CACERT\""
OS_CACERT="$(ls ${OS_CACERT/\~/$HOME})"
Expand All @@ -83,3 +87,5 @@ if test -n "$OS_CACERT"; then
else
helm upgrade -i openstack-secrets -n "$CS_NAMESPACE" --create-namespace https://github.com/SovereignCloudStack/openstack-csp-helper/releases/latest/download/openstack-csp-helper.tgz -f ~/tmp/clouds-$OS_CLOUD.yaml $OCTOVN
fi

echo "Cloud secret created successfully."
Loading