Loading pyinfra/kubeadm-clean.sh 0 → 100644 +267 −0 Original line number Diff line number Diff line #!/usr/bin/env bash # # kubeadm-clean.sh # # Completely cleans a kubeadm node so it can be initialized again. # # Usage: # sudo ./kubeadm-clean.sh # set -Eeuo pipefail ############################################# # Colors ############################################# RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[ OK ]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[FAIL]${NC} $*"; } ############################################# # Root check ############################################# if [[ $EUID -ne 0 ]]; then fail "Run this script with sudo or as root." exit 1 fi echo warn "This will completely remove Kubernetes, kubeadm, CNI and Calico state." sleep 3 ############################################# # Stop services ############################################# info "Stopping services..." systemctl stop kubelet 2>/dev/null || true systemctl stop containerd 2>/dev/null || true systemctl stop cri-o 2>/dev/null || true ############################################# # kubeadm reset ############################################# if command -v kubeadm >/dev/null 2>&1; then info "Running kubeadm reset..." kubeadm reset -f || true fi ############################################# # Remove containers and pods ############################################# if command -v crictl >/dev/null 2>&1; then info "Removing Kubernetes containers..." PODS=$(crictl pods -q 2>/dev/null || true) if [[ -n "$PODS" ]]; then crictl stopp $PODS 2>/dev/null || true crictl rmp $PODS 2>/dev/null || true fi CONTAINERS=$(crictl ps -aq 2>/dev/null || true) if [[ -n "$CONTAINERS" ]]; then crictl rm $CONTAINERS 2>/dev/null || true fi fi ############################################# # Remove CNI namespaces ############################################# info "Removing network namespaces..." ip netns list 2>/dev/null | awk '{print $1}' | while read -r ns do ip netns delete "$ns" 2>/dev/null || true done ############################################# # Remove Kubernetes directories ############################################# info "Removing Kubernetes directories..." DIRS=( /etc/kubernetes /var/lib/kubelet /var/lib/etcd /var/lib/cni /var/lib/calico /etc/cni/net.d "$HOME/.kube" ) for d in "${DIRS[@]}" do if [[ -e "$d" ]]; then rm -rf "$d" fi done ############################################# # Unmount Calico runtime (if mounted) ############################################# if mountpoint -q /var/run/calico/cgroup 2>/dev/null; then info "Unmounting Calico cgroup..." umount -l /var/run/calico/cgroup || true fi rmdir /var/run/calico 2>/dev/null || true ############################################# # Remove interfaces ############################################# info "Removing Kubernetes interfaces..." for iface in $(ip -o link show | awk -F': ' '{print $2}' | sed 's/@.*//') do case "$iface" in cali*|cni*|flannel*|vxlan.calico|vxlan-v6.calico|bpfin.cali|bpfout.cali) ip link delete "$iface" 2>/dev/null || true ;; esac done ############################################# # Flush routes ############################################# info "Removing CNI routes..." ip route | awk '/proto bird|cali|vxlan|cni/ {print $1}' | while read -r route do ip route del "$route" 2>/dev/null || true done ############################################# # Flush iptables ############################################# info "Flushing iptables..." for table in filter nat mangle raw security do iptables -t "$table" -F 2>/dev/null || true iptables -t "$table" -X 2>/dev/null || true done ip6tables -F 2>/dev/null || true ip6tables -X 2>/dev/null || true ############################################# # Clear IPVS ############################################# if command -v ipvsadm >/dev/null 2>&1; then info "Clearing IPVS..." ipvsadm --clear || true fi ############################################# # Restart runtime ############################################# info "Restarting container runtime..." systemctl restart containerd 2>/dev/null || true systemctl restart cri-o 2>/dev/null || true ############################################# # Verification ############################################# echo echo "================== VERIFICATION ==================" echo echo "[Directories]" for d in \ /etc/kubernetes \ /var/lib/kubelet \ /var/lib/etcd \ /var/lib/cni \ /var/lib/calico \ /etc/cni/net.d do if [[ -e "$d" ]]; then warn "$d exists" else ok "$d removed" fi done echo echo "[Interfaces]" if ip link | grep -Eq 'cali|cni|flannel|vxlan|bpf'; then warn "Interfaces still present:" ip link | grep -E 'cali|cni|flannel|vxlan|bpf' else ok "No Kubernetes interfaces." fi echo echo "[Network Namespaces]" if ip netns | grep -q .; then warn "Namespaces still present:" ip netns else ok "No network namespaces." fi echo echo "[CRI Pods]" if command -v crictl >/dev/null 2>&1; then if crictl pods -q | grep -q .; then warn "Pod sandboxes remain:" crictl pods else ok "No pod sandboxes." fi echo if crictl ps -aq | grep -q .; then warn "Containers remain:" crictl ps -a else ok "No containers." fi fi echo echo "[Services]" if systemctl is-active --quiet containerd; then ok "containerd running." else warn "containerd not running." fi if systemctl is-active --quiet kubelet; then warn "kubelet still running." else ok "kubelet stopped." fi echo echo "==================================================" echo ok "Cleanup completed." echo echo "Recommended:" echo " sudo reboot" echo echo "After reboot:" echo " sudo kubeadm init ..." echo " Install your CNI plugin." No newline at end of file pyinfra/lib/operations/meep.py +12 −12 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ def _build_env_prefix(target_home, node_version): @operation() def configure_sudoers(target_user): """ Idempotently create /etc/sudoers.d/meepctl with NOPASSWD rules for meepctl Create /etc/sudoers.d/meepctl with NOPASSWD rules for meepctl certificate trust operations (sudo cp, update-ca-certificates, systemctl restart). This operation must be called with _sudo=True so pyinfra handles authentication Loading @@ -43,10 +43,10 @@ def configure_sudoers(target_user): @operation() def install(mec_sandbox_dir, target_home, node_version): """ Idempotently install meepctl. Install meepctl. """ if host.get_fact(File, path=f"{target_home}/gocode/bin/meepctl"): return # if host.get_fact(File, path=f"{target_home}/gocode/bin/meepctl"): # return prefix = _build_env_prefix(target_home, node_version) yield StringCommand(f"{prefix} cd {mec_sandbox_dir}/go-apps/meepctl && bash install.sh") Loading @@ -54,15 +54,15 @@ def install(mec_sandbox_dir, target_home, node_version): @operation() def configure(ip, gitdir, target_home, node_version): """ Idempotently configure meepctl. Configure meepctl. """ if host.get_fact(File, path=f"{target_home}/.meep/.meepctl_configured"): return # if host.get_fact(File, path=f"{target_home}/.meep/.meepctl_configured"): # return prefix = _build_env_prefix(target_home, node_version) yield StringCommand(f"{prefix} meepctl config ip {ip}") yield StringCommand(f"{prefix} meepctl config gitdir {gitdir}") yield StringCommand(f"mkdir -p {target_home}/.meep && touch {target_home}/.meep/.meepctl_configured") # yield StringCommand(f"mkdir -p {target_home}/.meep && touch {target_home}/.meep/.meepctl_configured") @operation() def deploy_frontend(mec_frontend_dir, target_home, node_version): Loading @@ -79,7 +79,7 @@ def deploy_frontend(mec_frontend_dir, target_home, node_version): @operation() def configure_sandbox_secrets(mec_sandbox_dir, target_home, node_version): """ Idempotently configure MEC Sandbox secrets (secrets.yaml). Configure MEC Sandbox secrets (secrets.yaml). """ if not host.get_fact(File, path=f"{target_home}/.meep/.01_secrets_configured"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -90,7 +90,7 @@ def configure_sandbox_secrets(mec_sandbox_dir, target_home, node_version): @operation() def deploy_dep(mec_sandbox_dir, target_home, node_version, force=True): """ Idempotently deploy MEC Sandbox dependencies (meepctl deploy dep all). Deploy MEC Sandbox dependencies (meepctl deploy dep all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.02_deps_deployed"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -102,7 +102,7 @@ def deploy_dep(mec_sandbox_dir, target_home, node_version, force=True): @operation() def build_all(mec_sandbox_dir, target_home, node_version, nolint=True): """ Idempotently compile all MEC Sandbox binaries (meepctl build all). Compile all MEC Sandbox binaries (meepctl build all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.03_binaries_built"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -114,7 +114,7 @@ def build_all(mec_sandbox_dir, target_home, node_version, nolint=True): @operation() def dockerize_all(mec_sandbox_dir, target_home, node_version): """ Idempotently build and package all MEC Sandbox container images (meepctl dockerize all). Build and package all MEC Sandbox container images (meepctl dockerize all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.04_images_dockerized"): prefix = _build_env_prefix(target_home, node_version) Loading pyinfra/lib/scripts/verify_oauth.py +2 −2 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ def verify_github_oauth(client_id: str, client_secret: str): elif e.code in (404, 422): # 404 / 422 means Basic Auth succeeded for the application, but the dummy access token # was not found or unprocessable. This confirms the Client ID and Secret are valid! return True, f"Valid GitHub OAuth credentials (authenticated successfully, HTTP {e.code})" return True, f"Valid GitHub OAuth credentials (authenticated successfully, HTTP)" else: if attempt == 2: return True, f"Valid GitHub OAuth credentials (remote server HTTP {e.code} temporary note; proceeding with deployment)" Loading Loading @@ -101,7 +101,7 @@ def verify_gitlab_oauth(client_id: str, client_secret: str, gitlab_url: str = No elif e.code == 400: # 400 Bad Request typically means client authenticated, but client_credentials grant type # or redirect URI requirement was not satisfied. Since 401 was not returned, credentials are valid! return True, f"Valid GitLab OAuth credentials (authenticated successfully against {url}, HTTP 400)" return True, f"Valid GitLab OAuth credentials (authenticated successfully against {url}, HTTP)" else: if attempt == 2: # Treat temporary 5xx server errors on external GitLab instance as non-fatal Loading Loading
pyinfra/kubeadm-clean.sh 0 → 100644 +267 −0 Original line number Diff line number Diff line #!/usr/bin/env bash # # kubeadm-clean.sh # # Completely cleans a kubeadm node so it can be initialized again. # # Usage: # sudo ./kubeadm-clean.sh # set -Eeuo pipefail ############################################# # Colors ############################################# RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[ OK ]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } fail() { echo -e "${RED}[FAIL]${NC} $*"; } ############################################# # Root check ############################################# if [[ $EUID -ne 0 ]]; then fail "Run this script with sudo or as root." exit 1 fi echo warn "This will completely remove Kubernetes, kubeadm, CNI and Calico state." sleep 3 ############################################# # Stop services ############################################# info "Stopping services..." systemctl stop kubelet 2>/dev/null || true systemctl stop containerd 2>/dev/null || true systemctl stop cri-o 2>/dev/null || true ############################################# # kubeadm reset ############################################# if command -v kubeadm >/dev/null 2>&1; then info "Running kubeadm reset..." kubeadm reset -f || true fi ############################################# # Remove containers and pods ############################################# if command -v crictl >/dev/null 2>&1; then info "Removing Kubernetes containers..." PODS=$(crictl pods -q 2>/dev/null || true) if [[ -n "$PODS" ]]; then crictl stopp $PODS 2>/dev/null || true crictl rmp $PODS 2>/dev/null || true fi CONTAINERS=$(crictl ps -aq 2>/dev/null || true) if [[ -n "$CONTAINERS" ]]; then crictl rm $CONTAINERS 2>/dev/null || true fi fi ############################################# # Remove CNI namespaces ############################################# info "Removing network namespaces..." ip netns list 2>/dev/null | awk '{print $1}' | while read -r ns do ip netns delete "$ns" 2>/dev/null || true done ############################################# # Remove Kubernetes directories ############################################# info "Removing Kubernetes directories..." DIRS=( /etc/kubernetes /var/lib/kubelet /var/lib/etcd /var/lib/cni /var/lib/calico /etc/cni/net.d "$HOME/.kube" ) for d in "${DIRS[@]}" do if [[ -e "$d" ]]; then rm -rf "$d" fi done ############################################# # Unmount Calico runtime (if mounted) ############################################# if mountpoint -q /var/run/calico/cgroup 2>/dev/null; then info "Unmounting Calico cgroup..." umount -l /var/run/calico/cgroup || true fi rmdir /var/run/calico 2>/dev/null || true ############################################# # Remove interfaces ############################################# info "Removing Kubernetes interfaces..." for iface in $(ip -o link show | awk -F': ' '{print $2}' | sed 's/@.*//') do case "$iface" in cali*|cni*|flannel*|vxlan.calico|vxlan-v6.calico|bpfin.cali|bpfout.cali) ip link delete "$iface" 2>/dev/null || true ;; esac done ############################################# # Flush routes ############################################# info "Removing CNI routes..." ip route | awk '/proto bird|cali|vxlan|cni/ {print $1}' | while read -r route do ip route del "$route" 2>/dev/null || true done ############################################# # Flush iptables ############################################# info "Flushing iptables..." for table in filter nat mangle raw security do iptables -t "$table" -F 2>/dev/null || true iptables -t "$table" -X 2>/dev/null || true done ip6tables -F 2>/dev/null || true ip6tables -X 2>/dev/null || true ############################################# # Clear IPVS ############################################# if command -v ipvsadm >/dev/null 2>&1; then info "Clearing IPVS..." ipvsadm --clear || true fi ############################################# # Restart runtime ############################################# info "Restarting container runtime..." systemctl restart containerd 2>/dev/null || true systemctl restart cri-o 2>/dev/null || true ############################################# # Verification ############################################# echo echo "================== VERIFICATION ==================" echo echo "[Directories]" for d in \ /etc/kubernetes \ /var/lib/kubelet \ /var/lib/etcd \ /var/lib/cni \ /var/lib/calico \ /etc/cni/net.d do if [[ -e "$d" ]]; then warn "$d exists" else ok "$d removed" fi done echo echo "[Interfaces]" if ip link | grep -Eq 'cali|cni|flannel|vxlan|bpf'; then warn "Interfaces still present:" ip link | grep -E 'cali|cni|flannel|vxlan|bpf' else ok "No Kubernetes interfaces." fi echo echo "[Network Namespaces]" if ip netns | grep -q .; then warn "Namespaces still present:" ip netns else ok "No network namespaces." fi echo echo "[CRI Pods]" if command -v crictl >/dev/null 2>&1; then if crictl pods -q | grep -q .; then warn "Pod sandboxes remain:" crictl pods else ok "No pod sandboxes." fi echo if crictl ps -aq | grep -q .; then warn "Containers remain:" crictl ps -a else ok "No containers." fi fi echo echo "[Services]" if systemctl is-active --quiet containerd; then ok "containerd running." else warn "containerd not running." fi if systemctl is-active --quiet kubelet; then warn "kubelet still running." else ok "kubelet stopped." fi echo echo "==================================================" echo ok "Cleanup completed." echo echo "Recommended:" echo " sudo reboot" echo echo "After reboot:" echo " sudo kubeadm init ..." echo " Install your CNI plugin." No newline at end of file
pyinfra/lib/operations/meep.py +12 −12 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ def _build_env_prefix(target_home, node_version): @operation() def configure_sudoers(target_user): """ Idempotently create /etc/sudoers.d/meepctl with NOPASSWD rules for meepctl Create /etc/sudoers.d/meepctl with NOPASSWD rules for meepctl certificate trust operations (sudo cp, update-ca-certificates, systemctl restart). This operation must be called with _sudo=True so pyinfra handles authentication Loading @@ -43,10 +43,10 @@ def configure_sudoers(target_user): @operation() def install(mec_sandbox_dir, target_home, node_version): """ Idempotently install meepctl. Install meepctl. """ if host.get_fact(File, path=f"{target_home}/gocode/bin/meepctl"): return # if host.get_fact(File, path=f"{target_home}/gocode/bin/meepctl"): # return prefix = _build_env_prefix(target_home, node_version) yield StringCommand(f"{prefix} cd {mec_sandbox_dir}/go-apps/meepctl && bash install.sh") Loading @@ -54,15 +54,15 @@ def install(mec_sandbox_dir, target_home, node_version): @operation() def configure(ip, gitdir, target_home, node_version): """ Idempotently configure meepctl. Configure meepctl. """ if host.get_fact(File, path=f"{target_home}/.meep/.meepctl_configured"): return # if host.get_fact(File, path=f"{target_home}/.meep/.meepctl_configured"): # return prefix = _build_env_prefix(target_home, node_version) yield StringCommand(f"{prefix} meepctl config ip {ip}") yield StringCommand(f"{prefix} meepctl config gitdir {gitdir}") yield StringCommand(f"mkdir -p {target_home}/.meep && touch {target_home}/.meep/.meepctl_configured") # yield StringCommand(f"mkdir -p {target_home}/.meep && touch {target_home}/.meep/.meepctl_configured") @operation() def deploy_frontend(mec_frontend_dir, target_home, node_version): Loading @@ -79,7 +79,7 @@ def deploy_frontend(mec_frontend_dir, target_home, node_version): @operation() def configure_sandbox_secrets(mec_sandbox_dir, target_home, node_version): """ Idempotently configure MEC Sandbox secrets (secrets.yaml). Configure MEC Sandbox secrets (secrets.yaml). """ if not host.get_fact(File, path=f"{target_home}/.meep/.01_secrets_configured"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -90,7 +90,7 @@ def configure_sandbox_secrets(mec_sandbox_dir, target_home, node_version): @operation() def deploy_dep(mec_sandbox_dir, target_home, node_version, force=True): """ Idempotently deploy MEC Sandbox dependencies (meepctl deploy dep all). Deploy MEC Sandbox dependencies (meepctl deploy dep all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.02_deps_deployed"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -102,7 +102,7 @@ def deploy_dep(mec_sandbox_dir, target_home, node_version, force=True): @operation() def build_all(mec_sandbox_dir, target_home, node_version, nolint=True): """ Idempotently compile all MEC Sandbox binaries (meepctl build all). Compile all MEC Sandbox binaries (meepctl build all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.03_binaries_built"): prefix = _build_env_prefix(target_home, node_version) Loading @@ -114,7 +114,7 @@ def build_all(mec_sandbox_dir, target_home, node_version, nolint=True): @operation() def dockerize_all(mec_sandbox_dir, target_home, node_version): """ Idempotently build and package all MEC Sandbox container images (meepctl dockerize all). Build and package all MEC Sandbox container images (meepctl dockerize all). """ if not host.get_fact(File, path=f"{target_home}/.meep/.04_images_dockerized"): prefix = _build_env_prefix(target_home, node_version) Loading
pyinfra/lib/scripts/verify_oauth.py +2 −2 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ def verify_github_oauth(client_id: str, client_secret: str): elif e.code in (404, 422): # 404 / 422 means Basic Auth succeeded for the application, but the dummy access token # was not found or unprocessable. This confirms the Client ID and Secret are valid! return True, f"Valid GitHub OAuth credentials (authenticated successfully, HTTP {e.code})" return True, f"Valid GitHub OAuth credentials (authenticated successfully, HTTP)" else: if attempt == 2: return True, f"Valid GitHub OAuth credentials (remote server HTTP {e.code} temporary note; proceeding with deployment)" Loading Loading @@ -101,7 +101,7 @@ def verify_gitlab_oauth(client_id: str, client_secret: str, gitlab_url: str = No elif e.code == 400: # 400 Bad Request typically means client authenticated, but client_credentials grant type # or redirect URI requirement was not satisfied. Since 401 was not returned, credentials are valid! return True, f"Valid GitLab OAuth credentials (authenticated successfully against {url}, HTTP 400)" return True, f"Valid GitLab OAuth credentials (authenticated successfully against {url}, HTTP)" else: if attempt == 2: # Treat temporary 5xx server errors on external GitLab instance as non-fatal Loading