Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
sudo mv kubectl /usr/local/bin/

# Install helmfile
curl -L https://github.com/helmfile/helmfile/releases/download/v0.156.0/helmfile_0.156.0_linux_amd64.tar.gz | tar xz
curl -L https://github.com/helmfile/helmfile/releases/download/v1.2.3/helmfile_1.2.3_linux_amd64.tar.gz | tar xz
sudo mv helmfile /usr/local/bin/

echo "βœ… All prerequisites installed successfully"
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# Grounds Development Infrastructure (grounds-dev) .gitignore
# Ignores temporary files, build artifacts, and sensitive data

# Kubernetes and Helm artifacts
*.kubeconfig
*.kubeconfig.backup
Expand Down
3 changes: 0 additions & 3 deletions .shellcheckrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# ShellCheck configuration for Grounds Development Infrastructure
# Ensures consistent shell script quality and security

# Disable specific warnings that are acceptable for this project
disable=SC1091,SC2034,SC2155,SC2164

Expand Down
3 changes: 0 additions & 3 deletions .yamllint
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# yamllint configuration for Grounds Development Infrastructure
# Ensures consistent YAML formatting across the repository

extends: default

rules:
Expand Down
17 changes: 0 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Grounds Development Infrastructure (grounds-dev) Makefile
# Automation for local Kubernetes development environment
# Provides one-command setup and management of k3d cluster with PostgreSQL, Agones, and Open Match

SHELL := /usr/bin/env bash

# Colors for fancy output
Expand Down Expand Up @@ -109,16 +105,3 @@ test: ## Test the deployment
@echo -e "$(BLUE)ℹ️ Testing dummy HTTP server...$(NC)"
@curl -s http://localhost/demo || echo -e "$(YELLOW)⚠️ Dummy server not accessible (may still be starting)$(NC)"
@echo -e "$(GREEN)βœ… Tests completed$(NC)"

# Utility targets
.PHONY: check-prereqs
check-prereqs: ## Check prerequisites
@echo -e "$(BLUE)ℹ️ Checking prerequisites...$(NC)"
@./scripts/install-prereqs.sh --check-only || true

.PHONY: export-kubeconfig
export-kubeconfig: ## Export k3d cluster kubeconfig to ./kubeconfig
@echo -e "$(BLUE)ℹ️ Exporting kubeconfig...$(NC)"
@k3d kubeconfig get dev > kubeconfig
@echo -e "$(GREEN)βœ… Kubeconfig exported to ./kubeconfig$(NC)"
@echo -e "$(CYAN)Use it with: export KUBECONFIG=\$$(pwd)/kubeconfig$(NC)"
131 changes: 25 additions & 106 deletions cluster/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -1,42 +1,10 @@
#!/usr/bin/env bash
# Bootstrap script for Grounds Development Infrastructure (grounds-dev) k3d cluster
# Creates cluster, sets up namespaces, and configures Helm repositories

set -euo pipefail

# Colors and emojis for fancy console output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly PURPLE='\033[0;35m'
readonly CYAN='\033[0;36m'
readonly WHITE='\033[1;37m'
readonly NC='\033[0m' # No Color

# Logging functions
log_info() {
echo -e "${BLUE}ℹ️ $1${NC}"
}

log_success() {
echo -e "${GREEN}βœ… $1${NC}"
}

log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}

log_error() {
echo -e "${RED}❌ $1${NC}"
}

log_step() {
echo -e "${PURPLE}πŸš€ $1${NC}"
}

# Get script directory
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${here}/../scripts/common.sh"

log_step "Starting Grounds Development Infrastructure cluster bootstrap..."

Expand All @@ -56,20 +24,20 @@ if k3d cluster list | grep -q "^dev "; then
retry_count=0
cluster_healthy=false

while [ $retry_count -lt $max_retries ]; do
while [[ "${retry_count}" -lt "${max_retries}" ]]; do
if kubectl cluster-info >/dev/null 2>&1 && kubectl get nodes >/dev/null 2>&1; then
cluster_healthy=true
break
fi
retry_count=$((retry_count + 1))
log_warning "Cluster health check failed (attempt $retry_count/$max_retries), retrying in 5 seconds..."
log_warning "Cluster health check failed (attempt ${retry_count}/${max_retries}), retrying in 5 seconds..."
sleep 5
done

if [ "$cluster_healthy" = true ]; then
if [[ "${cluster_healthy}" = true ]]; then
log_success "Cluster 'dev' is healthy, skipping creation"
else
log_warning "Cluster 'dev' exists but is unhealthy after $max_retries attempts, recreating..."
log_warning "Cluster 'dev' exists but is unhealthy after ${max_retries} attempts, recreating..."
k3d cluster delete dev
log_step "Creating k3d cluster 'dev'..."
k3d cluster create --config "${here}/k3d.yaml"
Expand All @@ -86,33 +54,6 @@ log_info "Setting kubectl context to k3d-dev..."
kubectl config use-context k3d-dev
log_success "kubectl context set to k3d-dev"

# Export kubeconfig to project root
log_info "Exporting kubeconfig to ./kubeconfig..."
k3d kubeconfig get dev > "${here}/../kubeconfig"
log_success "Kubeconfig exported to ./kubeconfig"

# Install kubeconfig for kubectx if available
if command -v kubectx >/dev/null 2>&1; then
log_info "kubectx detected, installing kubeconfig to ~/.kube/config..."

# Ensure ~/.kube directory exists
mkdir -p "$HOME/.kube"

# Merge kubeconfigs using kubectl's native merge capability
if [ -f "$HOME/.kube/config" ]; then
KUBECONFIG="$HOME/.kube/config:${here}/../kubeconfig" kubectl config view --flatten > /tmp/merged-config
mv /tmp/merged-config "$HOME/.kube/config"
log_success "k3d-dev context merged into ~/.kube/config"
else
cp "${here}/../kubeconfig" "$HOME/.kube/config"
log_success "kubeconfig installed to ~/.kube/config"
fi

log_info "You can now use: kubectx k3d-dev"
else
log_info "kubectx not found, skipping kubeconfig installation to ~/.kube/"
fi

# Create namespaces
log_info "Creating namespaces..."
for ns in infra databases games api; do
Expand All @@ -123,7 +64,7 @@ log_success "Namespaces created: infra, databases, games, api"

# Load .env file if it exists
env_file="${here}/../.env"
if [ -f "${env_file}" ]; then
if [[ -f "${env_file}" ]]; then
log_info "Loading environment variables from .env file..."
set -a
# shellcheck source=/dev/null
Expand All @@ -135,19 +76,9 @@ else
fi

# Create GHCR pull secret if credentials are provided
if [ -n "${GHCR_USERNAME:-}" ] && [ -n "${GHCR_TOKEN:-}" ]; then
if [[ -n "${GHCR_USERNAME:-}" && -n "${GHCR_TOKEN:-}" ]]; then
log_step "Creating GHCR pull secret..."

# Create secret in default namespace
log_info "Creating ghcr-pull-secret in default namespace..."
kubectl create secret docker-registry ghcr-pull-secret \
--docker-server=ghcr.io \
--docker-username="${GHCR_USERNAME}" \
--docker-password="${GHCR_TOKEN}" \
--namespace=default \
--dry-run=client -o yaml | kubectl apply -f -
log_success "GHCR pull secret created in default namespace"

# Function to patch service account with GHCR pull secret
patch_service_account() {
local namespace=$1
Expand All @@ -156,25 +87,25 @@ if [ -n "${GHCR_USERNAME:-}" ] && [ -n "${GHCR_TOKEN:-}" ]; then
log_info "GHCR pull secret already configured in default service account for namespace: ${namespace}"
else
log_info "Patching default service account in namespace: ${namespace}"
# Create imagePullSecrets array if it doesn't exist
if ! kubectl get serviceaccount default -n "${namespace}" -o jsonpath='{.imagePullSecrets}' 2>/dev/null | grep -q "."; then
local pull_secrets_raw
pull_secrets_raw="$(kubectl get serviceaccount default -n "${namespace}" -o jsonpath='{.imagePullSecrets}' 2>/dev/null || true)"
if [[ -z "${pull_secrets_raw}" ]]; then
# Initialize imagePullSecrets so we can append entries later.
kubectl patch serviceaccount default \
--namespace="${namespace}" \
--type=json \
-p='[{"op": "add", "path": "/imagePullSecrets", "value": []}]' || true
-p='[{"op": "add", "path": "/imagePullSecrets", "value": [{"name": "ghcr-pull-secret"}]}]'
else
# Add the secret to the existing list.
kubectl patch serviceaccount default \
--namespace="${namespace}" \
--type=json \
-p='[{"op": "add", "path": "/imagePullSecrets/-", "value": {"name": "ghcr-pull-secret"}}]'
fi
# Add the secret to imagePullSecrets
kubectl patch serviceaccount default \
--namespace="${namespace}" \
--type=json \
-p='[{"op": "add", "path": "/imagePullSecrets/-", "value": {"name": "ghcr-pull-secret"}}]' || true
log_success "Default service account patched in namespace: ${namespace}"
fi
}

# Patch default service account in default namespace
patch_service_account default

# Create secret and patch service accounts in all namespaces
for ns in infra databases games api; do
log_info "Creating ghcr-pull-secret in namespace: ${ns}"
Expand All @@ -194,44 +125,32 @@ else
log_info "To enable GHCR authentication, set GHCR_USERNAME and GHCR_TOKEN in your .env file"
fi

# Add Helm repositories
log_step "Adding Helm repositories..."
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add agones https://agones.dev/chart/stable
log_success "Helm repositories added"

# Update Helm repositories
log_info "Updating Helm repository cache..."
helm repo update
log_success "Helm repositories updated"

# Verify cluster is ready with retry
log_info "Verifying cluster readiness..."
max_retries=5
retry_count=0
cluster_ready=false

while [ $retry_count -lt $max_retries ]; do
while [[ "${retry_count}" -lt "${max_retries}" ]]; do
if kubectl get nodes >/dev/null 2>&1; then
cluster_ready=true
break
fi
retry_count=$((retry_count + 1))
log_warning "Cluster readiness check failed (attempt $retry_count/$max_retries), retrying in 10 seconds..."
log_warning "Cluster readiness check failed (attempt ${retry_count}/${max_retries}), retrying in 10 seconds..."
sleep 10
done

if [ "$cluster_ready" = true ]; then
if [[ "${cluster_ready}" = true ]]; then
kubectl get nodes
log_success "Cluster is ready!"
else
log_error "Cluster failed to become ready after $max_retries attempts"
log_error "Cluster failed to become ready after ${max_retries} attempts"
exit 1
fi

log_step "Bootstrap completed successfully! πŸŽ‰"
log_info "Next steps:"
echo -e " ${CYAN}β€’${NC} Run ${WHITE}make up${NC} to deploy the full stack"
echo -e " ${CYAN}β€’${NC} Run ${WHITE}make status${NC} to check deployment status"
echo -e " ${CYAN}β€’${NC} Access services at ${WHITE}http://localhost${NC}"
echo -e " ${CYAN}β€’${NC} Use kubeconfig: ${WHITE}export KUBECONFIG=\$(pwd)/kubeconfig${NC}"
log_info "β€’ Run 'make up' to deploy the full stack"
log_info "β€’ Run 'make status' to check deployment status"
log_info "β€’ Access services at 'http://localhost'"
14 changes: 0 additions & 14 deletions cluster/k3d.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# k3d cluster configuration for local development
# This creates a lightweight Kubernetes cluster with 1 server + 2 agents
# Includes integrated registry and ingress port mapping for local development

apiVersion: k3d.io/v1alpha5
kind: Simple
metadata:
Expand All @@ -11,7 +7,6 @@ metadata:
servers: 1
agents: 2

# Use k3s version 1.34.1 for stability and compatibility
image: rancher/k3s:v1.34.1-k3s1

# Port mappings for ingress traffic
Expand Down Expand Up @@ -41,15 +36,6 @@ registries:
username: ${DOCKER_USERNAME}
password: ${DOCKER_PASSWORD}

# k3d and k3s options
options:
k3d:
wait: true # Wait for cluster to be ready before returning
# k3s:
# extraArgs:
# # Keep ServiceLB enabled for LoadBalancer services
# - arg: --disable=servicelb=false
# nodeFilters: [server:0]
# # Keep Traefik enabled for ingress controller
# - arg: --disable=traefik=false
# nodeFilters: [server:0]
4 changes: 0 additions & 4 deletions helmfile.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Helmfile configuration for grounds-dev
# Orchestrates deployment of PostgreSQL and Agones
# Uses declarative approach with proper dependency management

# Helm repositories
repositories:
- name: bitnami
Expand Down
28 changes: 28 additions & 0 deletions scripts/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Colors and emojis for log output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly PURPLE='\033[0;35m'
readonly NC='\033[0m' # No Color

# Logging functions
log_info() {
echo -e "${BLUE}ℹ️ $1${NC}"
}

log_success() {
echo -e "${GREEN}βœ… $1${NC}"
}

log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}

log_error() {
echo -e "${RED}❌ $1${NC}"
}

log_step() {
echo -e "${PURPLE}πŸš€ $1${NC}"
}
Loading