Skip to content

Commit

Permalink
Regoranized and centralized functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jaydrogers committed Nov 8, 2024
1 parent 05d01df commit ce52756
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 127 deletions.
14 changes: 3 additions & 11 deletions lib/actions/base64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ action_base64() {
local action=$1
local input=$2

if [[ "$(uname -s)" == "Darwin" ]]; then
local base64_encode_cmd="base64 -i"
local base64_decode_cmd="base64 -D"
else
local base64_encode_cmd="base64"
local base64_decode_cmd="base64 -d"
fi

case "$action" in
encode | -e)
# Check if the file exists for encoding
Expand All @@ -25,16 +17,16 @@ action_base64() {
return 1
fi
# Encode the file with base64
$base64_encode_cmd "$input"
base64_encode "$input"
;;
decode | -d)
# Decode the input
if [ -f "$input" ]; then
# If it's a file, decode the file contents
cat "$input" | $base64_decode_cmd
base64_decode - < "$input"
else
# If it's not a file, assume it's a base64 string and try to decode it
echo "$input" | $base64_decode_cmd 2>/dev/null
echo "$input" | base64_decode - 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: Input is not a valid base64 string."
return 1
Expand Down
232 changes: 232 additions & 0 deletions lib/actions/configure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#!/usr/bin/env bash

#################################
# Main Action Handler
#################################
action_configure() {
case "$1" in
gha)
shift
configure_gha "$@"
;;
*)
show_usage "$1"
exit 1
;;
esac

}

#################################
# Helper Functions
#################################
configure_gha() {
if [ $# -eq 0 ]; then
echo "${BOLD}${RED}❌ No environment specified${RESET}"
echo "Usage: spin configure gha <environment>"
echo "Example: spin configure gha production"
return 1
fi

local gha_environment="$1"
shift # Remove the first argument
local gha_environment_uppercase=$(echo "$gha_environment" | tr '[:lower:]' '[:upper:]')

validate_repository_setup || exit 1

local environment_file
environment_file=$(validate_environment_file "$gha_environment") || exit 1

gh_set_env --base64 --variable "${gha_environment_uppercase}_ENV_FILE_BASE64" --file "$environment_file"

configure_gha_deployment_key "$@"
configure_gha_authorized_keys

}

configure_gha_deployment_key() {
local inventory_file="${SPIN_INVENTORY_FILE:-"/etc/ansible/collections/ansible_collections/serversideup/spin/plugins/inventory/spin-dynamic-inventory.sh"}"
local infrastructure_folder=".infrastructure"

if [ ! -d "$infrastructure_folder" ]; then
echo "${BOLD}${RED}❌ Infrastructure folder not found${RESET}"
echo "Please ensure you're in the root of your project."
return 1
fi

if [ ! -d "$infrastructure_folder/deploy-keys" ] || [ ! -f "$infrastructure_folder/deploy-keys/.gitignore" ]; then
mkdir -p "$infrastructure_folder/deploy-keys"
echo "*" > "$infrastructure_folder/deploy-keys/.gitignore"
echo "!.gitignore" >> "$infrastructure_folder/deploy-keys/.gitignore"
fi

if [ ! -f "$infrastructure_folder/deploy-keys/id_ed25519_deploy" ]; then
echo "🔑 Generating deployment key"
ssh-keygen -t ed25519 -C "deploy-key" -f "$infrastructure_folder/deploy-keys/id_ed25519_deploy" -N ""
echo "${BOLD}${GREEN}✅ Deployment key generated${RESET}"
else
echo "🔑 Using existing deployment key found at \"$infrastructure_folder/deploy-keys/id_ed25519_deploy\""
fi

# Read the public key content
local deploy_public_key
deploy_public_key=$(cat "$infrastructure_folder/deploy-keys/id_ed25519_deploy.pub")

echo "🔑 Adding deployment key to GitHub repository"
gh_set_env --variable "SSH_DEPLOY_PRIVATE_KEY" --file "$infrastructure_folder/deploy-keys/id_ed25519_deploy"

echo "🔐 Adding deployment key to servers"
prepare_ansible_args "$@"
run_ansible --allow-ssh --mount-path "$(pwd)" \
ansible-playbook serversideup.spin.update_deploy_key \
--inventory "$inventory_file" \
--extra-vars @./.spin.yml \
--extra-vars "deploy_public_key='$deploy_public_key'" \
"${SPIN_ANSIBLE_ARGS[@]}" \
"${SPIN_UNPROCESSED_ARGS[@]}"

echo "${BOLD}${GREEN}✅ Deployment key added to servers${RESET}"
}

configure_gha_authorized_keys() {
echo "🔑 Gathering authorized keys for sudo users"
local authorized_keys
authorized_keys=$(run_ansible --minimal-output --mount-path "$(pwd)" \
ansible-playbook serversideup.spin.get_sudo_keys \
--extra-vars @./.spin.yml \
| sed -n 's/.*"msg": "\(.*\)".*/\1/p' \
| sed 's/\\\\n/\n/g') # Handle the double escaped newlines

echo "🔑 Adding authorized keys to GitHub repository"
echo "$authorized_keys"

# Add the authorized keys to GitHub secrets
gh_set_env --variable "AUTHORIZED_KEYS" --value "$authorized_keys"

}

gh_set_env() {
local base64_encode=false
local variable=""
local file=""
local value=""

# Parse arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
--base64)
base64_encode=true
shift
;;
--variable)
variable="$2"
shift 2
;;
--file)
file="$2"
shift 2
;;
--value)
value="$2"
shift 2
;;
*)
echo "${BOLD}${RED}❌ Invalid argument: $1${RESET}"
return 1
;;
esac
done

# Validate required arguments
if [ -z "$variable" ] || { [ -z "$file" ] && [ -z "$value" ]; }; then
echo "${BOLD}${RED}❌ Missing required arguments. Need --variable and either --file or --value.${RESET}"
return 1
fi

if [ -n "$file" ] && [ -n "$value" ]; then
echo "${BOLD}${RED}❌ Cannot specify both --file and --value.${RESET}"
return 1
fi

# Get content from either file or value
local content
if [ -n "$file" ]; then
if [ "$base64_encode" = true ]; then
content=$(base64_encode "$file")
else
content=$(<"$file")
fi
else
if [ "$base64_encode" = true ]; then
content=$(echo -n "$value" | base64_encode -)
else
content="$value"
fi
fi

# Set the secret using the gh CLI
echo "$content" | run_gh secret set "$variable"

echo "${BOLD}${GREEN}✅ Successfully set $variable secret for GitHub Actions${RESET}"
}

is_gh_cli_authenticated() {
run_gh auth status >/dev/null 2>&1
}

is_github_repository() {
run_gh repo view --json name >/dev/null 2>&1
}

show_usage() {
echo "${BOLD}${RED}❌ Invalid command: $1${RESET}"
echo
echo "Usage: spin configure <command>"
echo
echo "Commands:"
echo " gha <environment> Configure GitHub Actions settings for specified environment"
}

repository_exists() {
git rev-parse --is-inside-work-tree >/dev/null 2>&1
}

validate_environment_file() {
local gha_environment="$1"
local env_file=".env.$gha_environment"

if [ -f "$env_file" ]; then
echo "$env_file" # Return the path if file exists
return 0
else
echo "${BOLD}${RED}❌ Environment file not found ($env_file)${RESET}" >&2
echo "Please ensure you have an environment variable file for the \"$gha_environment\" environment." >&2
echo "Create a file called $env_file and add your environment variables to it." >&2
echo "You can also change the environment by running \`spin configure gha <environment>\`." >&2
return 1
fi
}

validate_repository_setup() {
if ! repository_exists; then
echo "${BOLD}${RED}❌ Repository not detected.${RESET}"
echo "Please ensure you're in the root of your project. If you need to create a repository, run \`git init\` then \`spin gh repo create\` to create one."
return 1
fi

if ! is_gh_cli_authenticated; then
echo "${BOLD}${RED}❌ GitHub CLI is not authenticated${RESET}"
echo
echo "Please authenticate with GitHub CLI by running \`spin gh auth login\`"
return 1
fi

if ! is_github_repository; then
echo "${BOLD}${RED}❌ Repository is not connected to GitHub.${RESET}"
echo "This project must be connected to a GitHub repository to use GitHub Actions."
echo "Add a GitHub remote or run \`spin gh repo create\` to create a GitHub repository."
return 1
fi

return 0
}
5 changes: 5 additions & 0 deletions lib/actions/gh.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
action_gh() {
# Run GH CLI via Docker
run_gh "$@"
}
1 change: 1 addition & 0 deletions lib/actions/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ action_init() {
".github" \
".git" \
".infrastructure" \
"!.infrastructure/**/local-ca.pem" \
"Dockerfile" \
"docker-*.yml" \
".gitlab-ci.yml" \
Expand Down
58 changes: 3 additions & 55 deletions lib/actions/maintain.sh
Original file line number Diff line number Diff line change
@@ -1,65 +1,13 @@
#!/usr/bin/env bash
action_maintain(){
additional_ansible_args=()
spin_remote_user="$USER" # Default to the current user who runs the command
force_ansible_upgrade=false
unprocessed_args=()
local inventory_file="${SPIN_INVENTORY_FILE:-"/etc/ansible/collections/ansible_collections/serversideup/spin/plugins/inventory/spin-dynamic-inventory.sh"}"

# Process arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
--host|-h)
additional_ansible_args+=("--extra-vars" "target=$2")
shift 2
;;
--user|-u)
spin_remote_user="$2" # Override default user with specified user
shift 2
;;
--port|-p)
additional_ansible_args+=("--extra-vars" "ansible_port=$2")
shift 2
;;
--upgrade|-U)
force_ansible_upgrade=true
shift
;;
*)
unprocessed_args+=("$1")
shift
;;
esac
done
prepare_ansible_args "$@"

echo "Starting Ansible..."
# Check if the Docker image exists and pull if it doesn't
if ! docker image inspect "${SPIN_ANSIBLE_IMAGE}" &> /dev/null; then
echo "Docker image ${SPIN_ANSIBLE_IMAGE} not found. Pulling..."
docker pull "${SPIN_ANSIBLE_IMAGE}"
fi

# Set Ansible User
additional_ansible_args+=("--extra-vars" "spin_remote_user=$spin_remote_user")
local use_passwordless_sudo
if ! use_passwordless_sudo=$(get_ansible_variable "use_passwordless_sudo"); then
echo "${BOLD}${RED}❌ Error: Failed to get ansible variable.${RESET}" >&2
exit 1
fi
use_passwordless_sudo=${use_passwordless_sudo:-"false"}
if [ "$spin_remote_user" != "root" ] && [ "$use_passwordless_sudo" = 'false' ]; then
additional_ansible_args+=("--ask-become-pass")
fi

# Append vault args to additional ansible args
IFS=' ' read -r -a vault_args < <(set_ansible_vault_args)
additional_ansible_args+=("${vault_args[@]}")

check_galaxy_pull "$force_ansible_upgrade"
run_ansible --allow-ssh --mount-path "$(pwd)" \
ansible-playbook serversideup.spin.maintain \
--inventory "$inventory_file" \
--extra-vars @./.spin.yml \
"${additional_ansible_args[@]}" \
"${unprocessed_args[@]}"
"${SPIN_ANSIBLE_ARGS[@]}" \
"${SPIN_UNPROCESSED_ARGS[@]}"
}
Loading

0 comments on commit ce52756

Please sign in to comment.