From 8bcc162956581e673aa40a8bf4ce3a5a3a7559af Mon Sep 17 00:00:00 2001 From: MichaelFisher1997 Date: Sat, 28 Feb 2026 16:31:23 +0000 Subject: [PATCH] feat: auto-discover kubeadm node IPs from terraform state --- .gitea/workflows/kubeadm-bootstrap.yml | 81 +++++++++++++++++++++----- .gitea/workflows/kubeadm-reset.yml | 81 +++++++++++++++++++++----- nixos/kubeadm/README.md | 12 ++-- terraform/outputs.tf | 14 +++++ 4 files changed, 158 insertions(+), 30 deletions(-) diff --git a/.gitea/workflows/kubeadm-bootstrap.yml b/.gitea/workflows/kubeadm-bootstrap.yml index 6e1b06a..7da5ae2 100644 --- a/.gitea/workflows/kubeadm-bootstrap.yml +++ b/.gitea/workflows/kubeadm-bootstrap.yml @@ -32,22 +32,77 @@ jobs: - name: Create SSH key run: | install -m 0700 -d ~/.ssh - cat > ~/.ssh/id_ed25519 << 'EOF' - ${{ secrets.KUBEADM_SSH_PRIVATE_KEY }} - EOF + KEY_CONTENT="$(printf '%s' "${{ secrets.KUBEADM_SSH_PRIVATE_KEY }}")" + if [ -z "$KEY_CONTENT" ]; then + KEY_CONTENT="$(printf '%s' "${{ secrets.SSH_KEY_PRIVATE }}")" + fi + + if [ -z "$KEY_CONTENT" ]; then + echo "Missing SSH private key secret. Set KUBEADM_SSH_PRIVATE_KEY or SSH_KEY_PRIVATE." + exit 1 + fi + + printf '%s\n' "$KEY_CONTENT" > ~/.ssh/id_ed25519 chmod 0600 ~/.ssh/id_ed25519 - - name: Create kubeadm inventory - working-directory: nixos/kubeadm/scripts + - name: Set up Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: 1.6.6 + terraform_wrapper: false + + - name: Build Terraform backend files + working-directory: terraform run: | - cat > inventory.env << EOF - SSH_USER=${{ secrets.KUBEADM_SSH_USER }} - CP_1=${{ secrets.KUBEADM_CP_1_IP }} - CP_2=${{ secrets.KUBEADM_CP_2_IP }} - CP_3=${{ secrets.KUBEADM_CP_3_IP }} - WK_1=${{ secrets.KUBEADM_WK_1_IP }} - WK_2=${{ secrets.KUBEADM_WK_2_IP }} - WK_3=${{ secrets.KUBEADM_WK_3_IP }} + cat > secrets.auto.tfvars << EOF + pm_api_token_secret = "${{ secrets.PM_API_TOKEN_SECRET }}" + SSH_KEY_PUBLIC = "$(printf '%s' "${{ secrets.SSH_KEY_PUBLIC }}" | tr -d '\r\n')" + EOF + + cat > backend.hcl << EOF + bucket = "${{ secrets.B2_TF_BUCKET }}" + key = "terraform.tfstate" + region = "us-east-005" + endpoints = { + s3 = "${{ secrets.B2_TF_ENDPOINT }}" + } + access_key = "$(printf '%s' "${{ secrets.B2_KEY_ID }}" | tr -d '\r\n')" + secret_key = "$(printf '%s' "${{ secrets.B2_APPLICATION_KEY }}" | tr -d '\r\n')" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + use_path_style = true + EOF + + - name: Terraform init for state read + working-directory: terraform + run: terraform init -reconfigure -backend-config=backend.hcl + + - name: Create kubeadm inventory + run: | + TF_OUTPUT_JSON="$(terraform -chdir=terraform output -json)" + + CP_1="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-1"])' <<< "$TF_OUTPUT_JSON")" + CP_2="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-2"])' <<< "$TF_OUTPUT_JSON")" + CP_3="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-3"])' <<< "$TF_OUTPUT_JSON")" + WK_1="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-1"])' <<< "$TF_OUTPUT_JSON")" + WK_2="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-2"])' <<< "$TF_OUTPUT_JSON")" + WK_3="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-3"])' <<< "$TF_OUTPUT_JSON")" + + SSH_USER="$(printf '%s' "${{ secrets.KUBEADM_SSH_USER }}")" + if [ -z "$SSH_USER" ]; then + SSH_USER="micqdf" + fi + + cat > nixos/kubeadm/scripts/inventory.env << EOF + SSH_USER=$SSH_USER + CP_1=$CP_1 + CP_2=$CP_2 + CP_3=$CP_3 + WK_1=$WK_1 + WK_2=$WK_2 + WK_3=$WK_3 EOF - name: Validate nix installation diff --git a/.gitea/workflows/kubeadm-reset.yml b/.gitea/workflows/kubeadm-reset.yml index 998b2e6..a7b04c5 100644 --- a/.gitea/workflows/kubeadm-reset.yml +++ b/.gitea/workflows/kubeadm-reset.yml @@ -32,22 +32,77 @@ jobs: - name: Create SSH key run: | install -m 0700 -d ~/.ssh - cat > ~/.ssh/id_ed25519 << 'EOF' - ${{ secrets.KUBEADM_SSH_PRIVATE_KEY }} - EOF + KEY_CONTENT="$(printf '%s' "${{ secrets.KUBEADM_SSH_PRIVATE_KEY }}")" + if [ -z "$KEY_CONTENT" ]; then + KEY_CONTENT="$(printf '%s' "${{ secrets.SSH_KEY_PRIVATE }}")" + fi + + if [ -z "$KEY_CONTENT" ]; then + echo "Missing SSH private key secret. Set KUBEADM_SSH_PRIVATE_KEY or SSH_KEY_PRIVATE." + exit 1 + fi + + printf '%s\n' "$KEY_CONTENT" > ~/.ssh/id_ed25519 chmod 0600 ~/.ssh/id_ed25519 - - name: Create kubeadm inventory - working-directory: nixos/kubeadm/scripts + - name: Set up Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: 1.6.6 + terraform_wrapper: false + + - name: Build Terraform backend files + working-directory: terraform run: | - cat > inventory.env << EOF - SSH_USER=${{ secrets.KUBEADM_SSH_USER }} - CP_1=${{ secrets.KUBEADM_CP_1_IP }} - CP_2=${{ secrets.KUBEADM_CP_2_IP }} - CP_3=${{ secrets.KUBEADM_CP_3_IP }} - WK_1=${{ secrets.KUBEADM_WK_1_IP }} - WK_2=${{ secrets.KUBEADM_WK_2_IP }} - WK_3=${{ secrets.KUBEADM_WK_3_IP }} + cat > secrets.auto.tfvars << EOF + pm_api_token_secret = "${{ secrets.PM_API_TOKEN_SECRET }}" + SSH_KEY_PUBLIC = "$(printf '%s' "${{ secrets.SSH_KEY_PUBLIC }}" | tr -d '\r\n')" + EOF + + cat > backend.hcl << EOF + bucket = "${{ secrets.B2_TF_BUCKET }}" + key = "terraform.tfstate" + region = "us-east-005" + endpoints = { + s3 = "${{ secrets.B2_TF_ENDPOINT }}" + } + access_key = "$(printf '%s' "${{ secrets.B2_KEY_ID }}" | tr -d '\r\n')" + secret_key = "$(printf '%s' "${{ secrets.B2_APPLICATION_KEY }}" | tr -d '\r\n')" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + use_path_style = true + EOF + + - name: Terraform init for state read + working-directory: terraform + run: terraform init -reconfigure -backend-config=backend.hcl + + - name: Create kubeadm inventory + run: | + TF_OUTPUT_JSON="$(terraform -chdir=terraform output -json)" + + CP_1="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-1"])' <<< "$TF_OUTPUT_JSON")" + CP_2="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-2"])' <<< "$TF_OUTPUT_JSON")" + CP_3="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["control_plane_vm_ipv4"]["value"]["cp-3"])' <<< "$TF_OUTPUT_JSON")" + WK_1="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-1"])' <<< "$TF_OUTPUT_JSON")" + WK_2="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-2"])' <<< "$TF_OUTPUT_JSON")" + WK_3="$(python3 -c 'import json,sys; d=json.loads(sys.stdin.read()); print(d["worker_vm_ipv4"]["value"]["wk-3"])' <<< "$TF_OUTPUT_JSON")" + + SSH_USER="$(printf '%s' "${{ secrets.KUBEADM_SSH_USER }}")" + if [ -z "$SSH_USER" ]; then + SSH_USER="micqdf" + fi + + cat > nixos/kubeadm/scripts/inventory.env << EOF + SSH_USER=$SSH_USER + CP_1=$CP_1 + CP_2=$CP_2 + CP_3=$CP_3 + WK_1=$WK_1 + WK_2=$WK_2 + WK_3=$WK_3 EOF - name: Run cluster reset diff --git a/nixos/kubeadm/README.md b/nixos/kubeadm/README.md index 0b2a4d1..30e2873 100644 --- a/nixos/kubeadm/README.md +++ b/nixos/kubeadm/README.md @@ -124,10 +124,14 @@ Manual dispatch workflows are available: Required repository secrets: -- `KUBEADM_SSH_PRIVATE_KEY` -- `KUBEADM_SSH_USER` -- `KUBEADM_CP_1_IP`, `KUBEADM_CP_2_IP`, `KUBEADM_CP_3_IP` -- `KUBEADM_WK_1_IP`, `KUBEADM_WK_2_IP`, `KUBEADM_WK_3_IP` +- Existing Terraform/backend secrets used by current workflows (`B2_*`, `PM_API_TOKEN_SECRET`, `SSH_KEY_PUBLIC`) +- SSH private key: prefer `KUBEADM_SSH_PRIVATE_KEY`, fallback to existing `SSH_KEY_PRIVATE` + +Optional secrets: + +- `KUBEADM_SSH_USER` (defaults to `micqdf`) + +Node IPs are auto-discovered from Terraform state outputs (`control_plane_vm_ipv4`, `worker_vm_ipv4`), so you do not need per-node IP secrets. ## Notes diff --git a/terraform/outputs.tf b/terraform/outputs.tf index 8ec628f..c817350 100644 --- a/terraform/outputs.tf +++ b/terraform/outputs.tf @@ -9,6 +9,13 @@ output "control_plane_vm_names" { value = [for vm in proxmox_vm_qemu.control_planes : vm.name] } +output "control_plane_vm_ipv4" { + value = { + for vm in proxmox_vm_qemu.control_planes : + vm.name => vm.default_ipv4_address + } +} + output "worker_vm_ids" { value = { for i in range(var.worker_count) : @@ -19,3 +26,10 @@ output "worker_vm_ids" { output "worker_vm_names" { value = [for vm in proxmox_vm_qemu.workers : vm.name] } + +output "worker_vm_ipv4" { + value = { + for vm in proxmox_vm_qemu.workers : + vm.name => vm.default_ipv4_address + } +}