Compare commits

..

9 commits

Author SHA1 Message Date
jon brookes
2f11890779 feat: add .env file check and load it in startup script 2025-10-14 18:15:32 +01:00
jon brookes
a8f25e733c Merge branch 'feat/mvk-gcloud-template' of ssh://codeberg.org/headshed/infctl-cli into feat/mvk-gcloud-template 2025-10-14 18:05:46 +01:00
jon brookes
e0906c821d fix: change to repo dir 2025-10-14 18:01:55 +01:00
jon brookes
8f19558826 feat: update Forgejo deployment
add DNS update step and complete forgejo deployment after build
2025-10-14 17:52:00 +01:00
jon brookes
02b114e0e6 feat: add scripts for pre-flight checks and user input wait in k3s pipeline 2025-10-14 17:49:59 +01:00
jon brookes
f23e1c41ff feat: add .env file existence check and load it in startup script 2025-10-14 16:50:12 +01:00
jon brookes
b4c0f17b12 feat: add script to copy .env file to k3s-vm-1 after pre-flight checks 2025-10-14 16:32:05 +01:00
jon brookes
bb4d0cc701 feat: update Forgejo deployment URL and add installation check in startup script 2025-10-14 15:58:09 +01:00
jon brookes
8faa97a8bb feat: env INSTALL_LONGHORN
Add Ansible playbooks for Longhorn, MetalLB, and Traefik installation

conditional on presence of INSTALL_LONGHORN=true
2025-10-10 13:33:11 +01:00
13 changed files with 269 additions and 45 deletions

View file

View file

@ -26,7 +26,7 @@ spec:
- name: FORGEJO__repository__ENABLE_PUSH_CREATE_USER - name: FORGEJO__repository__ENABLE_PUSH_CREATE_USER
value: "true" value: "true"
- name: FORGEJO__server__ROOT_URL - name: FORGEJO__server__ROOT_URL
value: "https://frg.headshed.dev/" value: "https://frgdr.headshed.dev/"
- name: FORGEJO__repository__DEFAULT_BRANCH - name: FORGEJO__repository__DEFAULT_BRANCH
value: "main" value: "main"
- name: FORGEJO__server__LFS_START_SERVER - name: FORGEJO__server__LFS_START_SERVER

View file

@ -0,0 +1,56 @@
[
{
"name": "run pre-flight checks",
"function": "RunCommand",
"params": [
"./gcloud/tf/scripts/pre-flight-checks.sh"
],
"retryCount": 0,
"shouldAbort": true
},
{
"name": "list gcloud infrastructure",
"function": "RunCommand",
"params": [
"./gcloud/tf/scripts/list_gloud_infra.sh"
],
"retryCount": 0,
"shouldAbort": true
},
{
"name": "create tfvars",
"function": "RunCommand",
"params": [
"./gcloud/tf/scripts/create_tfvars.sh"
],
"retryCount": 0,
"shouldAbort": true
},
{
"name": "run tofu",
"function": "RunCommand",
"params": [
"./gcloud/tf/scripts/run_tofu.sh"
],
"retryCount": 0,
"shouldAbort": true
},
{
"name": "wait for user input to continue",
"function": "RunCommand",
"params": [
"./gcloud/tf/scripts/wait_for_user_input_dns.sh"
],
"retryCount": 0,
"shouldAbort": true
},
{
"name": "copy .env to k3s-vm-1",
"function": "RunCommand",
"params": [
"gcloud/tf/scripts/copy_env_to_first_node.sh"
],
"retryCount": 0,
"shouldAbort": true
}
]

View file

@ -34,5 +34,14 @@
], ],
"retryCount": 0, "retryCount": 0,
"shouldAbort": true "shouldAbort": true
},
{
"name": "copy .env to k3s-vm-1",
"function": "RunCommand",
"params": [
"gcloud/tf/scripts/copy_env_to_first_node.sh"
],
"retryCount": 0,
"shouldAbort": true
} }
] ]

View file

@ -0,0 +1,31 @@
#!/usr/bin/env bash
source .env
for i in {1..10}; do
# Check if the instance is running
INSTANCE_STATUS=$(gcloud compute instances describe k3s-vm-1 --zone=us-central1-a --project="$PROJECT_NAME" --format='get(status)')
if [[ "$INSTANCE_STATUS" != "RUNNING" ]]; then
echo "Instance k3s-vm-1 is not running. Attempt $i/10. Waiting 5 seconds..."
sleep 5
continue
fi
# Check if the directory exists on the remote host
if gcloud compute ssh k3s-vm-1 --zone=us-central1-a --project="$PROJECT_NAME" --command="test -d /opt/src/infctl-cli/"; then
echo "/opt/src/infctl-cli/ exists on k3s-vm-1."
break
else
echo "/opt/src/infctl-cli/ does not exist yet. Attempt $i/10. Waiting 5 seconds..."
sleep 5
fi
done
# Final check after loop
if ! gcloud compute ssh k3s-vm-1 --zone=us-central1-a --project="$PROJECT_NAME" --command="test -d /opt/src/infctl-cli/"; then
echo "ERROR: /opt/src/infctl-cli/ does not exist on k3s-vm-1 after 10 attempts. Exiting."
exit 1
fi
gcloud compute scp .env k3s-vm-1:/opt/src/infctl-cli/.env --zone=us-central1-a --project=$PROJECT_NAME

View file

@ -1,5 +1,8 @@
#!/bin/bash #!/bin/bash
# Redirect all output to a log file for reliability
exec > /tmp/startup.log 2>&1
INFCTL_GIT_REPO="https://codeberg.org/headshed/infctl-cli.git" INFCTL_GIT_REPO="https://codeberg.org/headshed/infctl-cli.git"
INFCTL_GIT_REPO_BRANCH="main" INFCTL_GIT_REPO_BRANCH="main"
INFCTL_INSTALL_DIR="/opt/src" INFCTL_INSTALL_DIR="/opt/src"
@ -100,3 +103,32 @@ if [[ ! -d "$INFCTL_INSTALL_DIR" ]]; then
chown -R user:user "$INFCTL_INSTALL_DIR" chown -R user:user "$INFCTL_INSTALL_DIR"
fi fi
for i in {1..100}; do
if [[ -f /opt/src/infctl-cli/.env ]]; then
echo ".env file found."
break
else
echo ".env file not found. Attempt $i/100. Waiting 5 seconds..."
sleep 5
fi
done
# Final check after loop
if [[ ! -f /opt/src/infctl-cli/.env ]]; then
echo "ERROR: .env file not found after 10 attempts. Exiting."
exit 1
fi
# load .env file
source /opt/src/infctl-cli/.env
cd $INFCTL_INSTALL_DIR/infctl-cli || "echo 'Failed to change directory to $INFCTL_INSTALL_DIR/infctl-cli' ; exit 1"
# check to see if INSTALL_FORGEJO is set to "true"
if [[ "$INSTALL_FORGEJO" == "true" ]]; then
# install forgejo using infctl
# ....
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
LOG_FORMAT=none infctl -f "${INFCTL_INSTALL_DIR}/infctl-cli/gcloud/tf/scripts/install-forgejo-pipeline.json"
touch /etc/forgejo_was_installed
fi

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
echo "Please configure DNS using the IP address from the previous stage."
echo "you have 120 seconds."
for i in {120..1}; do
echo -ne "Time remaining: $i seconds\r"
sleep 1
done
echo ""
exit 0

View file

@ -117,7 +117,11 @@ Vagrant.configure("2") do |config|
vb.cpus = 1 vb.cpus = 1
end end
ws.vm.provision "shell", path: "ansible/provision_workstation.sh" ws.vm.provision "shell",
path: "ansible/provision_workstation.sh",
env: {
"INSTALL_LONGHORN" => ENV['INSTALL_LONGHORN'] || "false"
}
end end

View file

@ -0,0 +1,16 @@
---
- name: Install longhorn using infctl
hosts: localhost
become: true
become_user: vagrant
serial: 1 # Ensure tasks are executed one host at a time
vars_files:
- vars.yaml
tasks:
- name: run infctl longhorn pipeline
ansible.builtin.command: >
bash -c 'cd /home/vagrant && LOG_FILE=/tmp/longhorn_log.txt LOG_FORMAT=basic infctl -f pipelines/vagrant-longhorn.json'
register: longhorn_result
ignore_errors: false

View file

@ -0,0 +1,16 @@
---
- name: Install metallb using infctl
hosts: localhost
become: true
become_user: vagrant
serial: 1 # Ensure tasks are executed one host at a time
vars_files:
- vars.yaml
tasks:
- name: run ======== infctl metallb pipeline
ansible.builtin.command: >
bash -c 'cd /home/vagrant && LOG_FILE=/tmp/metallb_log.txt LOG_FORMAT=basic infctl -f ./pipelines/vagrant-metallb.json'
register: metallb_result
ignore_errors: false

View file

@ -0,0 +1,20 @@
---
- name: Install traefik using infctl
hosts: localhost
become: true
become_user: vagrant
serial: 1 # Ensure tasks are executed one host at a time
vars_files:
- vars.yaml
tasks:
- name: run infctl traefik pipeline
ansible.builtin.command: infctl -f pipelines/vagrant-ingress.json
args:
chdir: /home/vagrant
environment:
LOG_FILE: /tmp/traefik_log.txt
LOG_FORMAT: none
register: traefik_result
ignore_errors: false

View file

@ -4,6 +4,7 @@
sudo apt-get update sudo apt-get update
sudo apt-get install -y software-properties-common git vim python3.10-venv jq figlet sudo apt-get install -y software-properties-common git vim python3.10-venv jq figlet
# shellcheck disable=SC1091
source /vagrant/.envrc source /vagrant/.envrc
# Set up ansible environment for vagrant user # Set up ansible environment for vagrant user
@ -24,10 +25,10 @@ sudo chmod +x /home/vagrant/pipelines/*.sh
# Copy the Vagrant private keys (these will be synced by Vagrant) # Copy the Vagrant private keys (these will be synced by Vagrant)
for i in {1..3}; do for i in {1..3}; do
sudo -u vagrant cp /vagrant/.vagrant/machines/vm$i/virtualbox/private_key /home/vagrant/.ssh/vm${i}_key sudo -u vagrant cp "/vagrant/.vagrant/machines/vm$i/virtualbox/private_key" "/home/vagrant/.ssh/vm${i}_key"
sudo -u root cp /vagrant/.vagrant/machines/vm$i/virtualbox/private_key /root/.ssh/vm${i}_key sudo -u root cp "/vagrant/.vagrant/machines/vm$i/virtualbox/private_key" "/root/.ssh/vm${i}_key"
sudo chmod 600 /home/vagrant/.ssh/vm${i}_key sudo chmod 600 "/home/vagrant/.ssh/vm${i}_key"
sudo chmod 600 /root/.ssh/vm${i}_key sudo chmod 600 "/root/.ssh/vm${i}_key"
done done
# Disable host key checking for easier learning # Disable host key checking for easier learning
@ -46,18 +47,17 @@ cd "$ANSIBLE_DIR" || {
if [ ! -d "venv" ]; then if [ ! -d "venv" ]; then
echo "Creating Python virtual environment in ./venv..." echo "Creating Python virtual environment in ./venv..."
python3 -m venv venv python3 -m venv venv
source "venv/bin/activate" # shellcheck disable=SC1091
if [ $? -ne 0 ]; then if ! source "venv/bin/activate"; then
echo "Failed to activate virtual environment. Please check your Python installation." echo "Failed to activate virtual environment. Please check your Python installation."
exit 1 exit 1
fi fi
echo "Virtual environment created and activated." echo "Virtual environment created and activated."
cp /vagrant/ansible/requirements.txt . cp "/vagrant/ansible/requirements.txt" .
if [ -f "requirements.txt" ]; then if [ -f "requirements.txt" ]; then
echo "Installing dependencies from requirements.txt..." echo "Installing dependencies from requirements.txt..."
pip install --upgrade pip pip install --upgrade pip
pip install -r requirements.txt if ! pip install -r requirements.txt; then
if [ $? -ne 0 ]; then
echo "Failed to install dependencies from requirements.txt." echo "Failed to install dependencies from requirements.txt."
exit 1 exit 1
fi fi
@ -76,7 +76,13 @@ ls -al "$ANSIBLE_VENV_DIR/bin/activate"
if [ -d "$ANSIBLE_VENV_DIR" ]; then if [ -d "$ANSIBLE_VENV_DIR" ]; then
echo "Activating Ansible virtual environment..." echo "Activating Ansible virtual environment..."
source "$ANSIBLE_VENV_DIR/bin/activate" if [ -f "$ANSIBLE_VENV_DIR/bin/activate" ]; then
# shellcheck source=/dev/null
source "$ANSIBLE_VENV_DIR/bin/activate"
else
echo "Virtualenv activate script not found!" >&2
exit 1
fi
else else
echo "Ansible virtual environment not found at $ANSIBLE_VENV_DIR. Please create it before running this script." echo "Ansible virtual environment not found at $ANSIBLE_VENV_DIR. Please create it before running this script."
exit 1 exit 1
@ -86,13 +92,13 @@ echo ""
ansible --version ansible --version
if [ $? -ne 0 ]; then if ! ansible --version; then
echo "Ansible is not installed or not found in the virtual environment. Please check your installation." echo "Ansible is not installed or not found in the virtual environment. Please check your installation."
exit 1 exit 1
fi fi
eval `ssh-agent -s` eval "$(ssh-agent -s)"
ssh-add # ~/machines/*/virtualbox/private_key ssh-add # ~/machines/*/virtualbox/private_key
BASHRC="/home/vagrant/.bashrc" BASHRC="/home/vagrant/.bashrc"
@ -103,9 +109,10 @@ if ! grep -qF "$BLOCK_START" "$BASHRC"; then
cat <<'EOF' >> "$BASHRC" cat <<'EOF' >> "$BASHRC"
# ADDED BY infctl provisioning # ADDED BY infctl provisioning
eval `ssh-agent -s` eval "$(ssh-agent -s)"
ssh-add ~/machines/*/virtualbox/private_key ssh-add ~/machines/*/virtualbox/private_key
ssh-add -L ssh-add -L
# shellcheck disable=SC1091
source /vagrant/.envrc source /vagrant/.envrc
EOF EOF
else else
@ -125,48 +132,63 @@ echo
ssh-add ~/.ssh/vm*_key ssh-add ~/.ssh/vm*_key
ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible --inventory-file /home/vagrant/ansible/ansible_inventory.ini -m ping vm1,vm2,vm3 if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible --inventory-file /home/vagrant/ansible/ansible_inventory.ini -m ping vm1,vm2,vm3; then
if [ $? -ne 0 ]; then
echo "Ansible ping failed. Please check your Vagrant VMs and network configuration." echo "Ansible ping failed. Please check your Vagrant VMs and network configuration."
exit 1 exit 1
fi fi
# install_keepalived.yaml # install_keepalived.yaml
ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_keepalived.yaml --inventory-file ansible_inventory.ini if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_keepalived.yaml --inventory-file ansible_inventory.ini; then
if [ $? -ne 0 ]; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration." echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1 exit 1
fi fi
echo "Keepalived installation completed." echo "Keepalived installation completed."
# install_k3s_3node.yaml # install_k3s_3node.yaml
ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_k3s_3node.yaml --inventory-file ansible_inventory.ini if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_k3s_3node.yaml --inventory-file ansible_inventory.ini; then
if [ $? -ne 0 ]; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration." echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1 exit 1
fi fi
# copy_k8s_config.yaml # copy_k8s_config.yaml
ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook copy_k8s_config.yaml --inventory-file ansible_inventory.ini if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook copy_k8s_config.yaml --inventory-file ansible_inventory.ini; then
if [ $? -ne 0 ]; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration." echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1 exit 1
fi fi
ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_dnsmasq.yaml --inventory-file ansible_inventory.ini if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_dnsmasq.yaml --inventory-file ansible_inventory.ini; then
if [ $? -ne 0 ]; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration." echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1 exit 1
fi fi
# Wait for Kubernetes API to be ready
echo "Waiting for 30 seconds for Kubernetes API to be ready..."
sleep 30
echo "done waiting for kubernetes API"
# check infctl # check infctl
cd /home/vagrant cd /home/vagrant || exit
bash /home/vagrant/scripts/check_install_infctl.sh if ! bash /home/vagrant/scripts/check_install_infctl.sh; then
if [ $? -ne 0 ]; then
echo "infctl check failed. Please check your installation." echo "infctl check failed. Please check your installation."
exit 1 exit 1
fi fi
# Optionally install Longhorn, MetalLB, and Traefik
if [ "${INSTALL_LONGHORN}" = "true" ]; then
cd /home/vagrant/ansible || { echo "Failed to change directory to /home/vagrant/ansible"; exit 1; }
if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_longhorn.yaml --inventory-file ansible_inventory.ini; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1
fi
if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_metallb.yaml --inventory-file ansible_inventory.ini; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1
fi
if ! ANSIBLE_SUPPRESS_INTERPRETER_DISCOVERY_WARNING=1 ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook install_traefik.yaml --inventory-file ansible_inventory.ini; then
echo "Ansible playbook failed. Please check your Vagrant VMs and network configuration."
exit 1
fi
fi

View file

@ -12,24 +12,31 @@ if ! kubectl get deployment -n metallb-system controller &>/dev/null; then
exit 1 exit 1
fi fi
# Wait for MetalLB components to be ready echo "Waiting for MetalLB pods to be in 'Running' state..."
echo "Waiting for MetalLB components to be ready..." MAX_RETRIES=10
kubectl wait --namespace metallb-system \ RETRY=0
--for=condition=ready pod \
--selector=app=metallb \ while [ $RETRY -lt $MAX_RETRIES ]; do
--timeout=90s NOT_READY_PODS=$(kubectl -n metallb-system get pods --no-headers | grep -v 'Running' | wc -l)
if [ "$NOT_READY_PODS" -eq 0 ]; then
echo "All MetalLB pods are running."
break
else
echo "$NOT_READY_PODS MetalLB pods are not ready yet. Waiting..."
RETRY=$((RETRY + 1))
sleep 5
fi
done
if [ "$NOT_READY_PODS" -ne 0 ]; then
echo "Failed to get all MetalLB pods running after $MAX_RETRIES attempts."
exit 1
fi
else else
echo "MetalLB is already installed." echo "MetalLB is already installed."
fi fi
# Wait for the webhook service to be ready
echo "Waiting for MetalLB webhook service to be ready..."
kubectl wait --namespace metallb-system \
--for=condition=ready pod \
--selector=component=webhook \
--timeout=90s
# Check if the IPAddressPool already exists # Check if the IPAddressPool already exists
if ! kubectl get ipaddresspool -n metallb-system default &>/dev/null; then if ! kubectl get ipaddresspool -n metallb-system default &>/dev/null; then
echo "Creating MetalLB IPAddressPool..." echo "Creating MetalLB IPAddressPool..."