Initial commit.
This commit is contained in:
3
bin/README.md
Normal file
3
bin/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Sovereign Cloud Binaries
|
||||
|
||||
These are the scripts that help you manage your cloud.
|
||||
69
bin/chart-diff
Executable file
69
bin/chart-diff
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# chart-diff
|
||||
# Shows differences between current and new chart version using gomplate for values
|
||||
# Usage: chart-diff CHART [RELEASE_NAME] [NAMESPACE]
|
||||
|
||||
set -e
|
||||
|
||||
# Get script directories
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
# Load environment variables if needed
|
||||
if [[ -z "$ENVIRONMENT" ]]; then
|
||||
if [[ -f "${REPO_ROOT}/load-env.sh" ]]; then
|
||||
source "${REPO_ROOT}/load-env.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Print usage
|
||||
if [[ $# -lt 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
echo "Usage: $(basename $0) CHART [RELEASE_NAME] [NAMESPACE]"
|
||||
echo ""
|
||||
echo "Shows differences between current and new chart version."
|
||||
echo ""
|
||||
echo " CHART Chart name in charts/ directory"
|
||||
echo " RELEASE_NAME Release name (defaults to CHART)"
|
||||
echo " NAMESPACE Namespace (defaults to RELEASE_NAME)"
|
||||
echo ""
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CHART="$1"
|
||||
RELEASE_NAME="${2:-$CHART}"
|
||||
NAMESPACE="${3:-$RELEASE_NAME}"
|
||||
|
||||
# We use kubectl diff now, no need for helm-diff plugin
|
||||
|
||||
# Check if chart exists
|
||||
CHART_PATH="${REPO_ROOT}/charts/${CHART}"
|
||||
if [[ ! -d "$CHART_PATH" ]]; then
|
||||
echo "Error: Chart not found at ${CHART_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We'll use chart-template for values, so we don't need to check here
|
||||
|
||||
# Show what would change
|
||||
echo "==> Showing differences for chart: $CHART"
|
||||
echo "==> Release name: $RELEASE_NAME"
|
||||
echo "==> Namespace: $NAMESPACE"
|
||||
echo ""
|
||||
|
||||
# Create temporary files for the template output
|
||||
TEMP_OUTPUT=$(mktemp)
|
||||
CLEAN_OUTPUT=$(mktemp)
|
||||
|
||||
# Generate the template and filter out the header text
|
||||
"${SCRIPT_DIR}/chart-template" "$CHART" "$RELEASE_NAME" "$NAMESPACE" > "$TEMP_OUTPUT"
|
||||
sed -n '/^---$/,$p' "$TEMP_OUTPUT" > "$CLEAN_OUTPUT"
|
||||
|
||||
# Use kubectl diff to show actual differences between current state and template
|
||||
echo "==> Showing differences between current cluster state and template for $CHART:"
|
||||
echo "==> (+ indicates additions, - indicates removals)"
|
||||
echo ""
|
||||
kubectl diff -f "$CLEAN_OUTPUT" || true
|
||||
|
||||
# Clean up
|
||||
rm "$TEMP_OUTPUT" "$CLEAN_OUTPUT"
|
||||
108
bin/chart-install
Executable file
108
bin/chart-install
Executable file
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
# chart-install
|
||||
# Installs a Helm chart using gomplate for templating values
|
||||
# Usage: chart-install CHART [RELEASE_NAME] [NAMESPACE] [--dry-run]
|
||||
|
||||
set -e
|
||||
|
||||
# Get script directories
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
# Load environment variables if needed
|
||||
if [[ -z "$ENVIRONMENT" ]]; then
|
||||
if [[ -f "${REPO_ROOT}/load-env.sh" ]]; then
|
||||
source "${REPO_ROOT}/load-env.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Print usage
|
||||
if [[ $# -lt 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
echo "Usage: $(basename $0) CHART [RELEASE_NAME] [NAMESPACE] [--dry-run]"
|
||||
echo ""
|
||||
echo "Install or upgrade a chart with environment variable substitution."
|
||||
echo ""
|
||||
echo " CHART Chart name in charts/ directory"
|
||||
echo " RELEASE_NAME Release name (defaults to CHART)"
|
||||
echo " NAMESPACE Namespace (defaults to RELEASE_NAME)"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --dry-run Show what would be installed without actually installing"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for dry run flag
|
||||
DRY_RUN=false
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "--dry-run" ]; then
|
||||
DRY_RUN=true
|
||||
fi
|
||||
done
|
||||
|
||||
CHART="$1"
|
||||
RELEASE_NAME="${2:-$CHART}"
|
||||
NAMESPACE="${3:-$RELEASE_NAME}"
|
||||
|
||||
# Check if chart exists
|
||||
CHART_PATH="${REPO_ROOT}/charts/${CHART}"
|
||||
if [[ ! -d "$CHART_PATH" ]]; then
|
||||
echo "Error: Chart not found at ${CHART_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update chart dependencies if Chart.yaml has dependencies section
|
||||
if [ -f "${CHART_PATH}/Chart.yaml" ] && grep -q "dependencies:" "${CHART_PATH}/Chart.yaml"; then
|
||||
echo "Updating dependencies for chart: $CHART"
|
||||
helm dependency update "$CHART_PATH"
|
||||
fi
|
||||
|
||||
# We'll use chart-template for values, so we don't need to check here
|
||||
|
||||
# Create namespace (unless --dry-run was specified)
|
||||
if [ "$DRY_RUN" == "false" ]; then
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
|
||||
fi
|
||||
|
||||
# Run the helm command
|
||||
echo "Installing chart: $CHART as $RELEASE_NAME in namespace $NAMESPACE"
|
||||
|
||||
if [ "$DRY_RUN" == "true" ]; then
|
||||
echo "==> DRY RUN: Would install the following resources:"
|
||||
"${SCRIPT_DIR}/chart-template" "$CHART" "$RELEASE_NAME" "$NAMESPACE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# For actual installation, create a temporary file to capture template output
|
||||
TEMP_OUTPUT=$(mktemp)
|
||||
"${SCRIPT_DIR}/chart-template" "$CHART" "$RELEASE_NAME" "$NAMESPACE" > "$TEMP_OUTPUT"
|
||||
|
||||
# Apply the template to the cluster
|
||||
kubectl apply -f "$TEMP_OUTPUT"
|
||||
|
||||
# Clean up
|
||||
rm "$TEMP_OUTPUT"
|
||||
|
||||
# Print helpful information (if not dry run)
|
||||
if [ "$DRY_RUN" == "false" ]; then
|
||||
echo ""
|
||||
echo "✅ Successfully installed/upgraded $RELEASE_NAME in namespace $NAMESPACE"
|
||||
echo ""
|
||||
echo "To check the status:"
|
||||
echo " kubectl get all -n $NAMESPACE -l app.kubernetes.io/instance=$RELEASE_NAME"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Check for post-install instructions (only if not dry run)
|
||||
if [ "$DRY_RUN" == "false" ]; then
|
||||
INSTRUCTIONS_FILE="${CHART_PATH}/POST_INSTALL_NOTES.txt"
|
||||
if [[ -f "$INSTRUCTIONS_FILE" ]]; then
|
||||
# Process environment variables in instructions (using the same environment)
|
||||
echo ""
|
||||
echo "Post-installation instructions:"
|
||||
echo "==============================="
|
||||
gomplate -f "$INSTRUCTIONS_FILE"
|
||||
else
|
||||
echo "For more information, see the documentation in ${CHART_PATH}/README.md"
|
||||
fi
|
||||
fi
|
||||
65
bin/chart-template
Executable file
65
bin/chart-template
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# chart-template
|
||||
# Renders the template for a Helm chart using gomplate for values files
|
||||
# Usage: chart-template CHART [RELEASE_NAME] [NAMESPACE]
|
||||
|
||||
set -e
|
||||
|
||||
# Get script directories
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
# Load environment variables if needed
|
||||
if [[ -f "${REPO_ROOT}/load-env.sh" ]]; then
|
||||
source "${REPO_ROOT}/load-env.sh"
|
||||
fi
|
||||
|
||||
# Print usage
|
||||
if [[ $# -lt 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
echo "Usage: $(basename $0) CHART [RELEASE_NAME] [NAMESPACE]"
|
||||
echo ""
|
||||
echo "Renders the Kubernetes templates for a chart with environment variable substitution."
|
||||
echo ""
|
||||
echo " CHART Chart name in charts/ directory"
|
||||
echo " RELEASE_NAME Release name (defaults to CHART)"
|
||||
echo " NAMESPACE Namespace (defaults to RELEASE_NAME)"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CHART="$1"
|
||||
RELEASE_NAME="${2:-$CHART}"
|
||||
NAMESPACE="${3:-$RELEASE_NAME}"
|
||||
|
||||
# Check if chart exists
|
||||
CHART_PATH="${REPO_ROOT}/charts/${CHART}"
|
||||
if [[ ! -d "$CHART_PATH" ]]; then
|
||||
echo "Error: Chart not found at ${CHART_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if template values file exists
|
||||
TPL_VALUES_FILE="${CHART_PATH}/values.template.yaml"
|
||||
if [[ ! -f "$TPL_VALUES_FILE" ]]; then
|
||||
echo "Error: Template values file not found at ${TPL_VALUES_FILE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set variables needed for template
|
||||
export RELEASE_NAME="$RELEASE_NAME"
|
||||
export NAMESPACE="$NAMESPACE"
|
||||
export CHART="$CHART"
|
||||
|
||||
# No headers - just let helm template output the YAML
|
||||
|
||||
# Create temporary values file with gomplate
|
||||
TEMP_VALUES=$(mktemp)
|
||||
gomplate -f "$TPL_VALUES_FILE" > "$TEMP_VALUES"
|
||||
|
||||
# Run helm template
|
||||
helm template "$RELEASE_NAME" "$CHART_PATH" \
|
||||
--namespace "$NAMESPACE" \
|
||||
--values "$TEMP_VALUES"
|
||||
|
||||
# Clean up
|
||||
rm "$TEMP_VALUES"
|
||||
30
bin/dashboard-token
Executable file
30
bin/dashboard-token
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set up colors for better readability
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# The namespace where the dashboard is installed
|
||||
NAMESPACE=kubernetes-dashboard
|
||||
|
||||
# Get the token
|
||||
TOKEN=$(kubectl -n $NAMESPACE get secret dashboard-admin-token -o jsonpath="{.data.token}" | base64 -d)
|
||||
|
||||
# Print instructions
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ ${GREEN}Kubernetes Dashboard Token${BLUE} ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo
|
||||
echo -e "${GREEN}Use this token to authenticate to the Kubernetes Dashboard:${NC}"
|
||||
echo
|
||||
echo -e "${PURPLE}$TOKEN${NC}"
|
||||
echo
|
||||
|
||||
# Save token to clipboard if xclip is available
|
||||
if command -v xclip &> /dev/null; then
|
||||
echo -n "$TOKEN" | xclip -selection clipboard
|
||||
echo -e "${GREEN}Token has been copied to your clipboard!${NC}"
|
||||
fi
|
||||
137
bin/deploy-service
Executable file
137
bin/deploy-service
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Default values
|
||||
SERVICE_NAME=""
|
||||
DRY_RUN=false
|
||||
|
||||
# Source environment variables from load-env.sh
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
if [ -f "$REPO_DIR/load-env.sh" ]; then
|
||||
source "$REPO_DIR/load-env.sh"
|
||||
fi
|
||||
|
||||
function show_help {
|
||||
echo "Usage: $0 SERVICE_NAME [options]"
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " SERVICE_NAME Name of the service to deploy (directory name in services/)"
|
||||
echo ""
|
||||
echo "Optional arguments:"
|
||||
echo " --dry-run Preview the processed configuration without applying"
|
||||
echo " --help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 example-app"
|
||||
echo " $0 blog --dry-run"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Legacy mode check for type-based commands
|
||||
if [[ "$1" == "--type" ]]; then
|
||||
echo "Warning: Using legacy mode (generate and deploy in one step)"
|
||||
echo "Consider using generate-service followed by deploy-service instead."
|
||||
echo "Continuing with legacy mode..."
|
||||
echo ""
|
||||
|
||||
# Capture all arguments
|
||||
ALL_ARGS="$@"
|
||||
|
||||
# Extract service name from arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
--name)
|
||||
SERVICE_NAME_LEGACY="$2"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Generate the service configuration first
|
||||
TMP_DIR=$(mktemp -d)
|
||||
TMP_FILE="$TMP_DIR/service.yaml"
|
||||
|
||||
$SCRIPT_DIR/generate-service $ALL_ARGS --output "$TMP_DIR"
|
||||
|
||||
# Now deploy it using the service name
|
||||
if [[ -n "$SERVICE_NAME_LEGACY" ]]; then
|
||||
exec $0 "$SERVICE_NAME_LEGACY"
|
||||
else
|
||||
echo "Error: Legacy mode requires --name parameter"
|
||||
exit 1
|
||||
fi
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Parse command-line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
show_help
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
# First non-option argument is the service name
|
||||
SERVICE_NAME="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate service name
|
||||
if [[ -z "$SERVICE_NAME" ]]; then
|
||||
echo "Error: SERVICE_NAME must be provided"
|
||||
show_help
|
||||
fi
|
||||
|
||||
# Construct the service file path
|
||||
SERVICE_FILE="$REPO_DIR/services/$SERVICE_NAME/service.yaml"
|
||||
if [[ ! -f "$SERVICE_FILE" ]]; then
|
||||
echo "Error: Service file not found for $SERVICE_NAME at $SERVICE_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create temporary file for the processed manifest
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
# Ensure DOMAIN is exported for template substitution
|
||||
export DOMAIN="$DOMAIN"
|
||||
|
||||
# Process the service file with variable substitution
|
||||
echo "Processing service file: $SERVICE_FILE"
|
||||
cat "$SERVICE_FILE" | envsubst > "$TEMP_FILE"
|
||||
|
||||
# Handle dry run mode
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
cat "$TEMP_FILE"
|
||||
rm "$TEMP_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract namespace from the processed file (for creating it if needed)
|
||||
NAMESPACE=$(grep -o "namespace: [a-zA-Z0-9_-]\+" "$TEMP_FILE" | head -1 | cut -d' ' -f2)
|
||||
if [[ -n "$NAMESPACE" ]]; then
|
||||
# Create the namespace if it doesn't exist (using kubectl create which is idempotent with --dry-run=client)
|
||||
echo "Creating namespace $NAMESPACE if it doesn't exist..."
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client | kubectl create -f - 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Apply the service
|
||||
echo "Applying service configuration..."
|
||||
kubectl apply -f "$TEMP_FILE"
|
||||
rm "$TEMP_FILE"
|
||||
|
||||
echo "✅ Service deployed successfully!"
|
||||
186
bin/generate-service
Executable file
186
bin/generate-service
Executable file
@@ -0,0 +1,186 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Source environment variables for defaults and domain settings
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
if [ -f "$SCRIPT_DIR/../load-env.sh" ]; then
|
||||
source "$SCRIPT_DIR/../load-env.sh"
|
||||
fi
|
||||
|
||||
# Default values
|
||||
SERVICE_TYPE=""
|
||||
SERVICE_NAME=""
|
||||
NAMESPACE=""
|
||||
IMAGE=""
|
||||
PORT=""
|
||||
SERVICE_DOMAIN=""
|
||||
OUTPUT_DIR=""
|
||||
|
||||
function show_help {
|
||||
echo "Usage: $0 --type [public|internal|database|microservice] --name SERVICE_NAME [options]"
|
||||
echo ""
|
||||
echo "Required arguments:"
|
||||
echo " --type TYPE Service type (public, internal, database, or microservice)"
|
||||
echo " --name NAME Service name"
|
||||
echo ""
|
||||
echo "Optional arguments:"
|
||||
echo " --namespace NAMESPACE Kubernetes namespace (defaults to service name)"
|
||||
echo " --image IMAGE Container image (defaults to nginx:latest for most types)"
|
||||
echo " --port PORT Container port (defaults to 80)"
|
||||
echo " --domain DOMAIN Custom domain (defaults to TYPE-specific domain)"
|
||||
echo " --output DIR Output directory (defaults to services/NAME)"
|
||||
echo " --help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 --type public --name blog"
|
||||
echo " $0 --type internal --name admin --image my-admin:v1 --port 8080"
|
||||
echo " $0 --type database --name mysql --image mysql:8.0 --port 3306"
|
||||
echo " $0 --type microservice --name auth --image auth-service:v1 --port 9000"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
--type)
|
||||
SERVICE_TYPE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--name)
|
||||
SERVICE_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--namespace)
|
||||
NAMESPACE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--image)
|
||||
IMAGE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--port)
|
||||
PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--domain)
|
||||
SERVICE_DOMAIN="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required parameters
|
||||
if [[ -z "$SERVICE_TYPE" ]]; then
|
||||
echo "Error: Service type is required"
|
||||
show_help
|
||||
fi
|
||||
|
||||
if [[ -z "$SERVICE_NAME" ]]; then
|
||||
echo "Error: Service name is required"
|
||||
show_help
|
||||
fi
|
||||
|
||||
# Validate service type
|
||||
if [[ "$SERVICE_TYPE" != "public" && "$SERVICE_TYPE" != "internal" && "$SERVICE_TYPE" != "database" && "$SERVICE_TYPE" != "microservice" ]]; then
|
||||
echo "Error: Invalid service type. Must be public, internal, database, or microservice."
|
||||
show_help
|
||||
fi
|
||||
|
||||
# Set defaults
|
||||
if [[ -z "$NAMESPACE" ]]; then
|
||||
NAMESPACE="$SERVICE_NAME"
|
||||
fi
|
||||
|
||||
if [[ -z "$IMAGE" ]]; then
|
||||
if [[ "$SERVICE_TYPE" == "database" ]]; then
|
||||
IMAGE="mariadb:10.6"
|
||||
else
|
||||
IMAGE="nginx:latest"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$PORT" ]]; then
|
||||
if [[ "$SERVICE_TYPE" == "database" ]]; then
|
||||
PORT="3306"
|
||||
else
|
||||
PORT="80"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$SERVICE_DOMAIN" ]]; then
|
||||
if [[ "$SERVICE_TYPE" == "public" ]]; then
|
||||
SERVICE_DOMAIN="\${SERVICE_NAME}.\${DOMAIN}"
|
||||
elif [[ "$SERVICE_TYPE" == "internal" ]]; then
|
||||
SERVICE_DOMAIN="\${SERVICE_NAME}.internal.\${DOMAIN}"
|
||||
elif [[ "$SERVICE_TYPE" == "microservice" ]]; then
|
||||
SERVICE_DOMAIN="\${SERVICE_NAME}.svc.\${DOMAIN}"
|
||||
else
|
||||
SERVICE_DOMAIN="\${SERVICE_NAME}.db.\${DOMAIN}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set default output directory if not provided
|
||||
if [[ -z "$OUTPUT_DIR" ]]; then
|
||||
OUTPUT_DIR="$SCRIPT_DIR/../services/$SERVICE_NAME"
|
||||
fi
|
||||
|
||||
echo "Generating $SERVICE_TYPE service configuration for: $SERVICE_NAME"
|
||||
echo "Namespace: $NAMESPACE"
|
||||
echo "Image: $IMAGE"
|
||||
echo "Port: $PORT"
|
||||
echo "Domain Template: $SERVICE_DOMAIN"
|
||||
echo "Output Directory: $OUTPUT_DIR"
|
||||
echo
|
||||
|
||||
# Get the appropriate template
|
||||
if [[ "$SERVICE_TYPE" == "microservice" ]]; then
|
||||
TEMPLATE_FILE="$SCRIPT_DIR/../services/templates/microservice/service.yaml"
|
||||
else
|
||||
TEMPLATE_FILE="$SCRIPT_DIR/../services/templates/${SERVICE_TYPE}-service/service.yaml"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$TEMPLATE_FILE" ]]; then
|
||||
echo "Error: Template file not found: $TEMPLATE_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create output directory if it doesn't exist
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Create the service YAML
|
||||
echo "Creating service configuration..."
|
||||
|
||||
# Prepare variables for substitution
|
||||
export SERVICE_NAME="$SERVICE_NAME"
|
||||
export SERVICE_NAMESPACE="$NAMESPACE"
|
||||
export SERVICE_IMAGE="\"$IMAGE\""
|
||||
export SERVICE_PORT="$PORT"
|
||||
export SERVICE_DOMAIN="$SERVICE_DOMAIN"
|
||||
|
||||
# Process the template with variable substitution
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Define which variables to replace - only those from command arguments
|
||||
VARS_TO_REPLACE='${SERVICE_NAME},${SERVICE_NAMESPACE},${SERVICE_IMAGE},${SERVICE_PORT},${SERVICE_DOMAIN}'
|
||||
|
||||
# Process the template, only substituting the variables from arguments
|
||||
cat "$TEMPLATE_FILE" | envsubst "$VARS_TO_REPLACE" > "$OUTPUT_DIR/service.yaml"
|
||||
|
||||
echo "✅ Service configuration generated successfully!"
|
||||
echo "Configuration file: $OUTPUT_DIR/service.yaml"
|
||||
echo ""
|
||||
echo "To deploy this service configuration:"
|
||||
echo " ./bin/deploy-service $SERVICE_NAME"
|
||||
echo ""
|
||||
echo "To customize further, edit the generated file before deployment."
|
||||
67
bin/install-ca-ubuntu
Executable file
67
bin/install-ca-ubuntu
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script installs the local CA certificate on Ubuntu systems to avoid
|
||||
# certificate warnings in browsers when accessing internal cloud services.
|
||||
|
||||
# Set up error handling
|
||||
set -e
|
||||
|
||||
# Define colors for better readability
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
CA_DIR="/home/payne/repos/cloud.payne.io-setup/ca"
|
||||
CA_FILE="$CA_DIR/ca.crt"
|
||||
TARGET_DIR="/usr/local/share/ca-certificates"
|
||||
TARGET_FILE="cloud-payne-local-ca.crt"
|
||||
|
||||
echo -e "${BLUE}=== Installing Local CA Certificate on Ubuntu ===${NC}"
|
||||
echo
|
||||
|
||||
# Check if CA file exists
|
||||
if [ ! -f "$CA_FILE" ]; then
|
||||
echo -e "${RED}CA certificate not found at $CA_FILE${NC}"
|
||||
echo -e "${YELLOW}Please run the create-local-ca script first:${NC}"
|
||||
echo -e "${BLUE}./bin/create-local-ca${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy to the system certificate directory
|
||||
echo -e "${YELLOW}Copying CA certificate to $TARGET_DIR/$TARGET_FILE...${NC}"
|
||||
sudo cp "$CA_FILE" "$TARGET_DIR/$TARGET_FILE"
|
||||
|
||||
# Update the CA certificates
|
||||
echo -e "${YELLOW}Updating system CA certificates...${NC}"
|
||||
sudo update-ca-certificates
|
||||
|
||||
# Update browsers' CA store (optional, for Firefox)
|
||||
if [ -d "$HOME/.mozilla" ]; then
|
||||
echo -e "${YELLOW}You may need to manually import the certificate in Firefox:${NC}"
|
||||
echo -e "1. Open Firefox"
|
||||
echo -e "2. Go to Preferences > Privacy & Security > Certificates"
|
||||
echo -e "3. Click 'View Certificates' > 'Authorities' tab"
|
||||
echo -e "4. Click 'Import' and select $CA_FILE"
|
||||
echo -e "5. Check 'Trust this CA to identify websites' and click OK"
|
||||
fi
|
||||
|
||||
# Check popular browsers
|
||||
if command -v google-chrome &> /dev/null; then
|
||||
echo -e "${YELLOW}For Chrome, the system-wide certificate should now be recognized${NC}"
|
||||
echo -e "${YELLOW}You may need to restart the browser${NC}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${GREEN}=== CA Certificate Installation Complete ===${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}System-wide CA certificate has been installed.${NC}"
|
||||
echo -e "${YELLOW}You should now be able to access the Kubernetes Dashboard without certificate warnings:${NC}"
|
||||
echo -e "${BLUE}https://kubernetes-dashboard.in.cloud.payne.io${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}If you still see certificate warnings, try:${NC}"
|
||||
echo "1. Restart your browser"
|
||||
echo "2. Clear your browser's cache and cookies"
|
||||
echo "3. If using a non-standard browser, you may need to import the certificate manually"
|
||||
echo
|
||||
211
bin/setup-systemd-resolved-dns
Executable file
211
bin/setup-systemd-resolved-dns
Executable file
@@ -0,0 +1,211 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set up error handling
|
||||
set -e
|
||||
|
||||
# Define colors for better readability
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Load environment variables
|
||||
if [ -f "$(dirname "$0")/../load-env.sh" ]; then
|
||||
echo -e "${YELLOW}Loading environment variables...${NC}"
|
||||
source "$(dirname "$0")/../load-env.sh"
|
||||
fi
|
||||
|
||||
# Get cluster IP
|
||||
echo -e "${YELLOW}Getting cluster IP address...${NC}"
|
||||
CLUSTER_IP=$(kubectl get -n kube-system service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
|
||||
if [ -z "$CLUSTER_IP" ]; then
|
||||
echo -e "${RED}Failed to get cluster IP. Is Traefik running?${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Using cluster IP: ${CLUSTER_IP}${NC}"
|
||||
|
||||
# Domain settings
|
||||
DOMAIN="cloud.payne.io"
|
||||
INTERNAL_DOMAIN="in.${DOMAIN}"
|
||||
DASHBOARD_DOMAIN="kubernetes-dashboard.${INTERNAL_DOMAIN}"
|
||||
|
||||
echo -e "${BLUE}=== Setting up Split DNS with systemd-resolved ===${NC}"
|
||||
echo -e "${YELLOW}Internal Domain: ${INTERNAL_DOMAIN}${NC}"
|
||||
echo -e "${YELLOW}Dashboard Domain: ${DASHBOARD_DOMAIN}${NC}"
|
||||
echo
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}This script must be run as root to configure systemd-resolved.${NC}"
|
||||
echo -e "${YELLOW}Please run: sudo $0${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create systemd-resolved configuration directory if it doesn't exist
|
||||
echo -e "${YELLOW}Creating systemd-resolved configuration directory...${NC}"
|
||||
mkdir -p /etc/systemd/resolved.conf.d/
|
||||
|
||||
# Create the configuration file for split DNS
|
||||
echo -e "${YELLOW}Creating split DNS configuration...${NC}"
|
||||
cat > /etc/systemd/resolved.conf.d/split-dns.conf << EOF
|
||||
[Resolve]
|
||||
# Use Google DNS servers as fallback
|
||||
FallbackDNS=8.8.8.8 8.8.4.4
|
||||
|
||||
# Define our domain for special handling
|
||||
Domains=~${INTERNAL_DOMAIN}
|
||||
|
||||
# Enable split DNS
|
||||
DNSStubListenerExtra=${CLUSTER_IP}
|
||||
EOF
|
||||
|
||||
# Create a static host entry for the dashboard domain
|
||||
echo -e "${YELLOW}Creating static address mapping for ${DASHBOARD_DOMAIN}...${NC}"
|
||||
mkdir -p /etc/systemd/resolved.conf.d/
|
||||
|
||||
cat > /etc/systemd/resolved.conf.d/static-domains.conf << EOF
|
||||
[Resolve]
|
||||
# Map our dashboard domain to the cluster IP
|
||||
$(echo "${DASHBOARD_DOMAIN} ${CLUSTER_IP}" | awk '{print "DNS=" $2 "#" $1}')
|
||||
EOF
|
||||
|
||||
# Restart systemd-resolved
|
||||
echo -e "${YELLOW}Restarting systemd-resolved...${NC}"
|
||||
systemctl restart systemd-resolved
|
||||
|
||||
# Remove immutable flag from resolv.conf if set
|
||||
if lsattr /etc/resolv.conf 2>/dev/null | grep -q 'i'; then
|
||||
echo -e "${YELLOW}Removing immutable flag from /etc/resolv.conf...${NC}"
|
||||
chattr -i /etc/resolv.conf
|
||||
fi
|
||||
|
||||
# Configure resolv.conf to use systemd-resolved
|
||||
echo -e "${YELLOW}Configuring /etc/resolv.conf to use systemd-resolved...${NC}"
|
||||
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
|
||||
|
||||
# Now for the Kubernetes parts
|
||||
echo -e "${YELLOW}Setting up Kubernetes components...${NC}"
|
||||
|
||||
# Get email for Let's Encrypt
|
||||
echo -e "${YELLOW}Please enter an email address for Let's Encrypt registration:${NC}"
|
||||
read -p "Email: " EMAIL_ADDRESS
|
||||
|
||||
# Ensure cert-manager namespace exists
|
||||
kubectl get namespace cert-manager >/dev/null 2>&1 || kubectl create namespace cert-manager
|
||||
|
||||
# Install cert-manager if needed
|
||||
if ! kubectl get deployment -n cert-manager cert-manager >/dev/null 2>&1; then
|
||||
echo -e "${YELLOW}Installing cert-manager...${NC}"
|
||||
helm repo add jetstack https://charts.jetstack.io
|
||||
helm repo update
|
||||
helm upgrade --install cert-manager jetstack/cert-manager \
|
||||
--namespace cert-manager \
|
||||
--set installCRDs=true
|
||||
|
||||
# Wait for cert-manager to be ready
|
||||
echo -e "${YELLOW}Waiting for cert-manager to be ready (this may take a minute)...${NC}"
|
||||
sleep 30
|
||||
kubectl wait --for=condition=available --timeout=300s deployment/cert-manager -n cert-manager
|
||||
kubectl wait --for=condition=available --timeout=300s deployment/cert-manager-webhook -n cert-manager
|
||||
fi
|
||||
|
||||
# Ensure kubernetes-dashboard namespace exists
|
||||
kubectl get namespace kubernetes-dashboard >/dev/null 2>&1 || kubectl create namespace kubernetes-dashboard
|
||||
|
||||
# Install the dashboard if not already installed
|
||||
if ! kubectl get deployment -n kubernetes-dashboard kubernetes-dashboard >/dev/null 2>&1; then
|
||||
echo -e "${YELLOW}Installing Kubernetes Dashboard...${NC}"
|
||||
"$(dirname "$0")/install-simple-dashboard"
|
||||
fi
|
||||
|
||||
# Create a ClusterIssuer for Let's Encrypt
|
||||
echo -e "${YELLOW}Setting up Let's Encrypt ClusterIssuer...${NC}"
|
||||
cat << EOF | kubectl apply -f -
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: ${EMAIL_ADDRESS}
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: traefik
|
||||
EOF
|
||||
|
||||
# Check dashboard service name and port
|
||||
echo -e "${YELLOW}Checking kubernetes-dashboard service...${NC}"
|
||||
DASHBOARD_SERVICE=$(kubectl get svc -n kubernetes-dashboard -o name | grep kubernetes-dashboard | grep -v metrics-scraper | grep -v api | grep -v auth | head -1)
|
||||
|
||||
if [ -z "$DASHBOARD_SERVICE" ]; then
|
||||
echo -e "${RED}Kubernetes Dashboard service not found. Please check your installation.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the service name without the "service/" prefix
|
||||
DASHBOARD_SERVICE_NAME=$(echo $DASHBOARD_SERVICE | cut -d'/' -f2)
|
||||
echo -e "${YELLOW}Found dashboard service: ${DASHBOARD_SERVICE_NAME}${NC}"
|
||||
|
||||
# Get the service port
|
||||
DASHBOARD_PORT=$(kubectl get svc $DASHBOARD_SERVICE_NAME -n kubernetes-dashboard -o jsonpath='{.spec.ports[0].port}')
|
||||
echo -e "${YELLOW}Dashboard port: ${DASHBOARD_PORT}${NC}"
|
||||
|
||||
# Create an Ingress with TLS
|
||||
echo -e "${YELLOW}Creating ingress with TLS for ${DASHBOARD_DOMAIN}...${NC}"
|
||||
cat << EOF | kubectl apply -f -
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: traefik
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
traefik.ingress.kubernetes.io/service.serversscheme: https
|
||||
traefik.ingress.kubernetes.io/service.serverstransport.insecureskipverify: "true"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- ${DASHBOARD_DOMAIN}
|
||||
secretName: kubernetes-dashboard-tls
|
||||
rules:
|
||||
- host: ${DASHBOARD_DOMAIN}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: ${DASHBOARD_SERVICE_NAME}
|
||||
port:
|
||||
number: ${DASHBOARD_PORT}
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo -e "${GREEN}=== Split DNS Setup Complete! ===${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}Your Kubernetes Dashboard will be available at:${NC}"
|
||||
echo -e "${BLUE}https://${DASHBOARD_DOMAIN}${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}Key points:${NC}"
|
||||
echo "1. systemd-resolved is now configured to resolve ${INTERNAL_DOMAIN} domains locally"
|
||||
echo "2. The dashboard domain ${DASHBOARD_DOMAIN} is mapped to ${CLUSTER_IP}"
|
||||
echo "3. Let's Encrypt will issue a valid certificate for secure HTTPS (may take a few minutes)"
|
||||
echo "4. External users cannot access these domains (special DNS configuration required)"
|
||||
echo
|
||||
echo -e "${YELLOW}To test the DNS resolution:${NC}"
|
||||
echo -e "${BLUE}nslookup ${DASHBOARD_DOMAIN}${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}To verify systemd-resolved configuration:${NC}"
|
||||
echo -e "${BLUE}resolvectl status${NC}"
|
||||
echo
|
||||
echo -e "${YELLOW}Certificate status:${NC}"
|
||||
echo -e "${BLUE}kubectl get certificate -n kubernetes-dashboard${NC}"
|
||||
echo
|
||||
Reference in New Issue
Block a user