feat: update orchestrating script to use decoded SSH private key and enhance SSH connection validation; modify Dockerfile and docker-compose to streamline environment variable management

This commit is contained in:
2025-09-23 13:13:31 +08:00
parent 7fb9d24d3e
commit 975035a54a
3 changed files with 106 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
FROM alpine:latest FROM alpine:latest
RUN apk --no-cache add curl bash git doctl RUN apk --no-cache add curl bash git doctl openssh
WORKDIR /app WORKDIR /app

View File

@@ -28,8 +28,8 @@ check_doctl() {
# Function to setup SSH private key # Function to setup SSH private key
setup_ssh_key() { setup_ssh_key() {
if [ -z "$SSH_PRIVATE_KEY" ]; then if [ -z "$SSH_PRIVATE_KEY_DECODED" ]; then
echo "Error: SSH_PRIVATE_KEY environment variable is not set" echo "Error: SSH_PRIVATE_KEY_DECODED environment variable is not set"
exit 1 exit 1
fi fi
@@ -37,22 +37,62 @@ setup_ssh_key() {
mkdir -p ~/.ssh mkdir -p ~/.ssh
chmod 700 ~/.ssh chmod 700 ~/.ssh
# Write private key to file (decode if base64) # Decode base64 encoded SSH private key
if echo "$SSH_PRIVATE_KEY" | base64 -d > /dev/null 2>&1; then echo "$SSH_PRIVATE_KEY_DECODED" | base64 -d > ~/.ssh/id_rsa
echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
else # Ensure proper line endings for OpenSSH key format
echo -e "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa sed -i 's/\r$//' ~/.ssh/id_rsa
# Add final newline if missing
if [ -s ~/.ssh/id_rsa ] && [ "$(tail -c1 ~/.ssh/id_rsa | wc -l)" -eq 0 ]; then
echo >> ~/.ssh/id_rsa
fi fi
chmod 600 ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa
echo "SSH private key has been set up successfully" # Validate SSH key format
if ! ssh-keygen -y -f ~/.ssh/id_rsa > /dev/null 2>&1; then
echo "Error: Invalid SSH private key format"
echo "Key content preview (first 100 chars):"
head -c 100 ~/.ssh/id_rsa
echo
echo "Key file size: $(wc -c < ~/.ssh/id_rsa) bytes"
echo "Key file lines: $(wc -l < ~/.ssh/id_rsa) lines"
exit 1
fi
echo "SSH private key has been set up and validated successfully"
}
# Function to destroy droplet
destroy_droplet() {
local droplet_id="$1"
if [ -z "$droplet_id" ]; then
echo "Error: No droplet ID provided for destruction"
return 1
fi
echo "Destroying droplet with ID: $droplet_id"
# Authenticate doctl
doctl auth init --access-token "$DO_TOKEN"
# Destroy droplet
if doctl compute droplet delete "$droplet_id" --force; then
echo "Droplet $droplet_id destroyed successfully"
return 0
else
echo "Error: Failed to destroy droplet $droplet_id"
return 1
fi
} }
# Function to create droplet # Function to create droplet
create_droplet() { create_droplet() {
local name="${1:-runner-${RUNNER_ID}}" local name="${1:-runner-${RUNNER_ID}}"
local size="${2:-s-1vcpu-1gb}" local size="${2:-s-1vcpu-1gb}"
local image="${3:-ubuntu-22-04-x64}" local image="${3:-ubuntu-24-04-x64}"
local region="${4:-sgp1}" local region="${4:-sgp1}"
echo "Creating droplet: $name" echo "Creating droplet: $name"
@@ -79,6 +119,16 @@ create_droplet() {
local droplet_ip=$(doctl compute droplet get "$droplet_id" --format PublicIPv4 --no-header) local droplet_ip=$(doctl compute droplet get "$droplet_id" --format PublicIPv4 --no-header)
echo "Droplet IP: $droplet_ip" echo "Droplet IP: $droplet_ip"
# Test SSH connection
if test_ssh_connection "$droplet_ip"; then
echo "Droplet is ready and accessible via SSH"
else
echo "Warning: Droplet created but SSH connection failed"
echo "Destroying failed droplet..."
destroy_droplet "$droplet_id"
return 1
fi
return 0 return 0
else else
echo "Error: Failed to create droplet" echo "Error: Failed to create droplet"
@@ -86,8 +136,51 @@ create_droplet() {
fi fi
} }
# Function to test SSH connection
test_ssh_connection() {
local droplet_ip="$1"
local max_attempts=10
local attempt=1
local wait_time=30
echo "Testing SSH connection to $droplet_ip..."
while [ $attempt -le $max_attempts ]; do
echo "Attempt $attempt/$max_attempts: Testing SSH connection..."
# Test SSH connection with verbose error handling
ssh_output=$(ssh -i ~/.ssh/id_rsa \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=10 \
-o BatchMode=yes \
-o PasswordAuthentication=no \
root@"$droplet_ip" "echo 'SSH connection successful'" 2>&1)
ssh_exit_code=$?
if [ $ssh_exit_code -eq 0 ]; then
echo "SSH connection to $droplet_ip established successfully"
echo "Response: $ssh_output"
return 0
else
echo "SSH connection failed (exit code: $ssh_exit_code)"
echo "Error output: $ssh_output"
if [ $attempt -lt $max_attempts ]; then
echo "Waiting $wait_time seconds before retry..."
sleep $wait_time
fi
attempt=$((attempt + 1))
fi
done
echo "Error: Failed to establish SSH connection to $droplet_ip after $max_attempts attempts"
return 1
}
# Check required environment variables # Check required environment variables
check_env_vars "SPEC" "RUNNER_ID" "DO_TOKEN" "SSH_PRIVATE_KEY" check_env_vars "SPEC" "RUNNER_ID" "DO_TOKEN" "SSH_PRIVATE_KEY_DECODED"
# Check if doctl is available # Check if doctl is available
check_doctl check_doctl

View File

@@ -5,9 +5,7 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
entrypoint: "" entrypoint: ""
command: ["sleep", "3600"] command: ["sleep", "3600"]
environment: env_file:
- DO_TOKEN=dop_v1_edf8bb32e734cf0dbbb40ce9d2b7ad494277caced8636a4823aede610b6c31fa - .env
- RUNNER_ID=pandeganteng
- SPEC=default
volumes: volumes:
- ./actions:/actions - ./actions:/actions