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:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user