- Complete Particle-OS rebranding from uBlue-OS - Professional installation system with standardized paths - Self-initialization system with --init and --reset commands - Enhanced error messages and dependency checking - Comprehensive testing infrastructure - All source scriptlets updated with runtime improvements - Clean codebase with redundant files moved to archive - Complete documentation suite
641 lines
21 KiB
Bash
641 lines
21 KiB
Bash
#!/bin/bash
|
|
|
|
# Multi-Tenant Support for apt-layer
|
|
# Enables enterprise deployments with multiple organizations, departments, or environments
|
|
# Provides tenant isolation, resource quotas, and cross-tenant management
|
|
|
|
# Multi-tenant configuration
|
|
MULTI_TENANT_ENABLED="${MULTI_TENANT_ENABLED:-false}"
|
|
TENANT_ISOLATION_LEVEL="${TENANT_ISOLATION_LEVEL:-strict}" # strict, moderate, permissive
|
|
TENANT_RESOURCE_QUOTAS="${TENANT_RESOURCE_QUOTAS:-true}"
|
|
TENANT_CROSS_ACCESS="${TENANT_CROSS_ACCESS:-false}"
|
|
|
|
# Tenant management functions
|
|
init_multi_tenant_system() {
|
|
log_info "Initializing multi-tenant system..." "multi-tenant"
|
|
|
|
# Create tenant directories
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
mkdir -p "$tenant_base"
|
|
mkdir -p "$tenant_base/shared"
|
|
mkdir -p "$tenant_base/templates"
|
|
|
|
# Initialize tenant database
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
if [[ ! -f "$tenant_db" ]]; then
|
|
cat > "$tenant_db" << 'EOF'
|
|
{
|
|
"tenants": [],
|
|
"policies": {
|
|
"default_isolation": "strict",
|
|
"default_quotas": {
|
|
"max_layers": 100,
|
|
"max_storage_gb": 50,
|
|
"max_users": 10
|
|
},
|
|
"cross_tenant_access": false
|
|
},
|
|
"metadata": {
|
|
"created": "",
|
|
"version": "1.0"
|
|
}
|
|
}
|
|
EOF
|
|
# Set creation timestamp
|
|
jq --arg created "$(date -Iseconds)" '.metadata.created = $created' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
|
|
fi
|
|
|
|
log_success "Multi-tenant system initialized" "multi-tenant"
|
|
}
|
|
|
|
# Tenant creation and management
|
|
create_tenant() {
|
|
local tenant_name="$1"
|
|
local tenant_config="$2"
|
|
|
|
if [[ -z "$tenant_name" ]]; then
|
|
log_error "Tenant name is required" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Validate tenant name
|
|
if [[ ! "$tenant_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
|
log_error "Invalid tenant name: $tenant_name (use alphanumeric, underscore, hyphen only)" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
local tenant_dir="$tenant_base/$tenant_name"
|
|
|
|
# Check if tenant already exists
|
|
if jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
|
|
log_error "Tenant '$tenant_name' already exists" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Create tenant directory structure
|
|
mkdir -p "$tenant_dir"
|
|
mkdir -p "$tenant_dir/layers"
|
|
mkdir -p "$tenant_dir/deployments"
|
|
mkdir -p "$tenant_dir/users"
|
|
mkdir -p "$tenant_dir/audit"
|
|
mkdir -p "$tenant_dir/backups"
|
|
mkdir -p "$tenant_dir/config"
|
|
|
|
# Create tenant configuration
|
|
local tenant_config_file="$tenant_dir/config/tenant.json"
|
|
cat > "$tenant_config_file" << EOF
|
|
{
|
|
"name": "$tenant_name",
|
|
"created": "$(date -Iseconds)",
|
|
"status": "active",
|
|
"isolation_level": "$TENANT_ISOLATION_LEVEL",
|
|
"quotas": {
|
|
"max_layers": 100,
|
|
"max_storage_gb": 50,
|
|
"max_users": 10,
|
|
"used_layers": 0,
|
|
"used_storage_gb": 0,
|
|
"used_users": 0
|
|
},
|
|
"policies": {
|
|
"allowed_packages": [],
|
|
"blocked_packages": [],
|
|
"security_level": "standard",
|
|
"audit_retention_days": 90
|
|
},
|
|
"integrations": {
|
|
"oci_registries": [],
|
|
"external_audit": null,
|
|
"monitoring": null
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Merge custom configuration if provided
|
|
if [[ -n "$tenant_config" && -f "$tenant_config" ]]; then
|
|
if jq empty "$tenant_config" 2>/dev/null; then
|
|
jq -s '.[0] * .[1]' "$tenant_config_file" "$tenant_config" > "$tenant_config_file.tmp" && mv "$tenant_config_file.tmp" "$tenant_config_file"
|
|
else
|
|
log_warning "Invalid JSON in tenant configuration, using defaults" "multi-tenant"
|
|
fi
|
|
fi
|
|
|
|
# Add tenant to database
|
|
local tenant_info
|
|
tenant_info=$(jq -r '.' "$tenant_config_file")
|
|
jq --arg name "$tenant_name" --argjson info "$tenant_info" '.tenants += [$info]' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
|
|
|
|
log_success "Tenant '$tenant_name' created successfully" "multi-tenant"
|
|
log_info "Tenant directory: $tenant_dir" "multi-tenant"
|
|
}
|
|
|
|
# Tenant deletion
|
|
delete_tenant() {
|
|
local tenant_name="$1"
|
|
local force="${2:-false}"
|
|
|
|
if [[ -z "$tenant_name" ]]; then
|
|
log_error "Tenant name is required" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
local tenant_dir="$tenant_base/$tenant_name"
|
|
|
|
# Check if tenant exists
|
|
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
|
|
log_error "Tenant '$tenant_name' does not exist" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Check for active resources
|
|
local active_layers=0
|
|
local active_deployments=0
|
|
|
|
if [[ -d "$tenant_dir/layers" ]]; then
|
|
active_layers=$(find "$tenant_dir/layers" -name "*.squashfs" 2>/dev/null | wc -l)
|
|
fi
|
|
|
|
if [[ -d "$tenant_dir/deployments" ]]; then
|
|
active_deployments=$(find "$tenant_dir/deployments" -name "*.json" 2>/dev/null | wc -l)
|
|
fi
|
|
|
|
if [[ $active_layers -gt 0 || $active_deployments -gt 0 ]]; then
|
|
if [[ "$force" != "true" ]]; then
|
|
log_error "Tenant '$tenant_name' has active resources ($active_layers layers, $active_deployments deployments)" "multi-tenant"
|
|
log_error "Use --force to delete anyway" "multi-tenant"
|
|
return 1
|
|
else
|
|
log_warning "Force deleting tenant with active resources" "multi-tenant"
|
|
fi
|
|
fi
|
|
|
|
# Remove from database
|
|
jq --arg name "$tenant_name" 'del(.tenants[] | select(.name == $name))' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
|
|
|
|
# Remove tenant directory
|
|
if [[ -d "$tenant_dir" ]]; then
|
|
rm -rf "$tenant_dir"
|
|
fi
|
|
|
|
log_success "Tenant '$tenant_name' deleted successfully" "multi-tenant"
|
|
}
|
|
|
|
# Tenant listing and information
|
|
list_tenants() {
|
|
local format="${1:-table}"
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
if [[ ! -f "$tenant_db" ]]; then
|
|
log_error "Tenant database not found" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
case "$format" in
|
|
"json")
|
|
jq -r '.' "$tenant_db"
|
|
;;
|
|
"csv")
|
|
echo "name,status,created,layers,storage_gb,users"
|
|
jq -r '.tenants[] | [.name, .status, .created, .quotas.used_layers, .quotas.used_storage_gb, .quotas.used_users] | @csv' "$tenant_db"
|
|
;;
|
|
"table"|*)
|
|
echo "Tenants:"
|
|
echo "========"
|
|
jq -r '.tenants[] | "\(.name) (\(.status)) - Layers: \(.quotas.used_layers)/\(.quotas.max_layers), Storage: \(.quotas.used_storage_gb)GB/\(.quotas.max_storage_gb)GB"' "$tenant_db"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Tenant information
|
|
get_tenant_info() {
|
|
local tenant_name="$1"
|
|
local format="${2:-json}"
|
|
|
|
if [[ -z "$tenant_name" ]]; then
|
|
log_error "Tenant name is required" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
local tenant_info
|
|
tenant_info=$(jq -r ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" 2>/dev/null)
|
|
|
|
if [[ -z "$tenant_info" ]]; then
|
|
log_error "Tenant '$tenant_name' not found" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
case "$format" in
|
|
"json")
|
|
echo "$tenant_info"
|
|
;;
|
|
"yaml")
|
|
echo "$tenant_info" | jq -r '.' | sed 's/^/ /'
|
|
;;
|
|
"summary")
|
|
local name status created layers storage users
|
|
name=$(echo "$tenant_info" | jq -r '.name')
|
|
status=$(echo "$tenant_info" | jq -r '.status')
|
|
created=$(echo "$tenant_info" | jq -r '.created')
|
|
layers=$(echo "$tenant_info" | jq -r '.quotas.used_layers')
|
|
storage=$(echo "$tenant_info" | jq -r '.quotas.used_storage_gb')
|
|
users=$(echo "$tenant_info" | jq -r '.quotas.used_users')
|
|
|
|
echo "Tenant: $name"
|
|
echo "Status: $status"
|
|
echo "Created: $created"
|
|
echo "Resources: $layers layers, ${storage}GB storage, $users users"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Tenant quota management
|
|
update_tenant_quotas() {
|
|
local tenant_name="$1"
|
|
local quota_type="$2"
|
|
local value="$3"
|
|
|
|
if [[ -z "$tenant_name" || -z "$quota_type" || -z "$value" ]]; then
|
|
log_error "Usage: update_tenant_quotas <tenant> <quota_type> <value>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
# Validate quota type
|
|
case "$quota_type" in
|
|
"max_layers"|"max_storage_gb"|"max_users")
|
|
;;
|
|
*)
|
|
log_error "Invalid quota type: $quota_type" "multi-tenant"
|
|
log_error "Valid types: max_layers, max_storage_gb, max_users" "multi-tenant"
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
# Update quota
|
|
jq --arg name "$tenant_name" --arg type "$quota_type" --arg value "$value" \
|
|
'.tenants[] | select(.name == $name) | .quotas[$type] = ($value | tonumber)' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
|
|
|
|
log_success "Updated quota for tenant '$tenant_name': $quota_type = $value" "multi-tenant"
|
|
}
|
|
|
|
# Tenant isolation and access control
|
|
check_tenant_access() {
|
|
local tenant_name="$1"
|
|
local user="$2"
|
|
local operation="$3"
|
|
|
|
if [[ -z "$tenant_name" || -z "$user" || -z "$operation" ]]; then
|
|
log_error "Usage: check_tenant_access <tenant> <user> <operation>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
# Check if tenant exists
|
|
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
|
|
log_error "Tenant '$tenant_name' not found" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Get tenant isolation level
|
|
local isolation_level
|
|
isolation_level=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .isolation_level" "$tenant_db")
|
|
|
|
# Check user access (simplified - in real implementation, this would check user roles)
|
|
local user_file="$tenant_base/$tenant_name/users/$user.json"
|
|
if [[ ! -f "$user_file" ]]; then
|
|
log_error "User '$user' not found in tenant '$tenant_name'" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Check operation permissions
|
|
local user_role
|
|
user_role=$(jq -r '.role' "$user_file" 2>/dev/null)
|
|
|
|
case "$operation" in
|
|
"read")
|
|
[[ "$user_role" =~ ^(admin|package_manager|viewer)$ ]] && return 0
|
|
;;
|
|
"write")
|
|
[[ "$user_role" =~ ^(admin|package_manager)$ ]] && return 0
|
|
;;
|
|
"admin")
|
|
[[ "$user_role" == "admin" ]] && return 0
|
|
;;
|
|
*)
|
|
log_error "Unknown operation: $operation" "multi-tenant"
|
|
return 1
|
|
;;
|
|
esac
|
|
|
|
log_error "Access denied: User '$user' with role '$user_role' cannot perform '$operation' operation" "multi-tenant"
|
|
return 1
|
|
}
|
|
|
|
# Tenant resource usage tracking
|
|
update_tenant_usage() {
|
|
local tenant_name="$1"
|
|
local resource_type="$2"
|
|
local amount="$3"
|
|
|
|
if [[ -z "$tenant_name" || -z "$resource_type" || -z "$amount" ]]; then
|
|
log_error "Usage: update_tenant_usage <tenant> <resource_type> <amount>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
# Update usage
|
|
jq --arg name "$tenant_name" --arg type "$resource_type" --arg amount "$amount" \
|
|
'.tenants[] | select(.name == $name) | .quotas["used_" + $type] = (.quotas["used_" + $type] + ($amount | tonumber))' "$tenant_db" > "$tenant_db.tmp" && mv "$tenant_db.tmp" "$tenant_db"
|
|
|
|
log_debug "Updated usage for tenant '$tenant_name': $resource_type += $amount" "multi-tenant"
|
|
}
|
|
|
|
# Tenant quota enforcement
|
|
enforce_tenant_quotas() {
|
|
local tenant_name="$1"
|
|
local resource_type="$2"
|
|
local requested_amount="$3"
|
|
|
|
if [[ -z "$tenant_name" || -z "$resource_type" || -z "$requested_amount" ]]; then
|
|
log_error "Usage: enforce_tenant_quotas <tenant> <resource_type> <amount>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
# Get current usage and quota
|
|
local current_usage max_quota
|
|
current_usage=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .quotas.used_$resource_type" "$tenant_db")
|
|
max_quota=$(jq -r ".tenants[] | select(.name == \"$tenant_name\") | .quotas.max_$resource_type" "$tenant_db")
|
|
|
|
# Check if request would exceed quota
|
|
local new_total=$((current_usage + requested_amount))
|
|
if [[ $new_total -gt $max_quota ]]; then
|
|
log_error "Quota exceeded for tenant '$tenant_name': $resource_type" "multi-tenant"
|
|
log_error "Current: $current_usage, Requested: $requested_amount, Max: $max_quota" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Cross-tenant operations (when enabled)
|
|
cross_tenant_operation() {
|
|
local source_tenant="$1"
|
|
local target_tenant="$2"
|
|
local operation="$3"
|
|
local user="$4"
|
|
|
|
if [[ "$TENANT_CROSS_ACCESS" != "true" ]]; then
|
|
log_error "Cross-tenant operations are disabled" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -z "$source_tenant" || -z "$target_tenant" || -z "$operation" || -z "$user" ]]; then
|
|
log_error "Usage: cross_tenant_operation <source> <target> <operation> <user>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Check user has admin access to both tenants
|
|
if ! check_tenant_access "$source_tenant" "$user" "admin"; then
|
|
log_error "User '$user' lacks admin access to source tenant '$source_tenant'" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
if ! check_tenant_access "$target_tenant" "$user" "admin"; then
|
|
log_error "User '$user' lacks admin access to target tenant '$target_tenant'" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
log_info "Cross-tenant operation: $operation from '$source_tenant' to '$target_tenant' by '$user'" "multi-tenant"
|
|
|
|
# Implement specific cross-tenant operations here
|
|
case "$operation" in
|
|
"copy_layer")
|
|
# Copy layer from source to target tenant
|
|
log_info "Copying layer between tenants..." "multi-tenant"
|
|
;;
|
|
"sync_config")
|
|
# Sync configuration between tenants
|
|
log_info "Syncing configuration between tenants..." "multi-tenant"
|
|
;;
|
|
*)
|
|
log_error "Unknown cross-tenant operation: $operation" "multi-tenant"
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Tenant backup and restore
|
|
backup_tenant() {
|
|
local tenant_name="$1"
|
|
local backup_path="$2"
|
|
|
|
if [[ -z "$tenant_name" ]]; then
|
|
log_error "Tenant name is required" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_dir="$tenant_base/$tenant_name"
|
|
|
|
if [[ ! -d "$tenant_dir" ]]; then
|
|
log_error "Tenant directory not found: $tenant_dir" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Create backup
|
|
local backup_file
|
|
if [[ -n "$backup_path" ]]; then
|
|
backup_file="$backup_path"
|
|
else
|
|
backup_file="$tenant_dir/backups/tenant-${tenant_name}-$(date +%Y%m%d-%H%M%S).tar.gz"
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$backup_file")"
|
|
|
|
tar -czf "$backup_file" -C "$tenant_base" "$tenant_name"
|
|
|
|
log_success "Tenant '$tenant_name' backed up to: $backup_file" "multi-tenant"
|
|
}
|
|
|
|
restore_tenant() {
|
|
local backup_file="$1"
|
|
local tenant_name="$2"
|
|
|
|
if [[ -z "$backup_file" || -z "$tenant_name" ]]; then
|
|
log_error "Usage: restore_tenant <backup_file> <tenant_name>" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -f "$backup_file" ]]; then
|
|
log_error "Backup file not found: $backup_file" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_dir="$tenant_base/$tenant_name"
|
|
|
|
# Check if tenant already exists
|
|
if [[ -d "$tenant_dir" ]]; then
|
|
log_error "Tenant '$tenant_name' already exists. Delete it first or use a different name." "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
# Restore tenant
|
|
tar -xzf "$backup_file" -C "$tenant_base"
|
|
|
|
log_success "Tenant '$tenant_name' restored from: $backup_file" "multi-tenant"
|
|
}
|
|
|
|
# Tenant health check
|
|
check_tenant_health() {
|
|
local tenant_name="$1"
|
|
|
|
if [[ -z "$tenant_name" ]]; then
|
|
log_error "Tenant name is required" "multi-tenant"
|
|
return 1
|
|
fi
|
|
|
|
local tenant_base="${WORKSPACE}/tenants"
|
|
local tenant_dir="$tenant_base/$tenant_name"
|
|
local tenant_db="$tenant_base/tenants.json"
|
|
|
|
echo "Tenant Health Check: $tenant_name"
|
|
echo "================================"
|
|
|
|
# Check tenant exists
|
|
if [[ ! -d "$tenant_dir" ]]; then
|
|
echo "❌ Tenant directory not found"
|
|
return 1
|
|
fi
|
|
|
|
if ! jq -e ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db" > /dev/null 2>&1; then
|
|
echo "❌ Tenant not found in database"
|
|
return 1
|
|
fi
|
|
|
|
echo "✅ Tenant exists"
|
|
|
|
# Check directory structure
|
|
local missing_dirs=()
|
|
for dir in layers deployments users audit backups config; do
|
|
if [[ ! -d "$tenant_dir/$dir" ]]; then
|
|
missing_dirs+=("$dir")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#missing_dirs[@]} -gt 0 ]]; then
|
|
echo "⚠️ Missing directories: ${missing_dirs[*]}"
|
|
else
|
|
echo "✅ Directory structure complete"
|
|
fi
|
|
|
|
# Check quota usage
|
|
local tenant_info
|
|
tenant_info=$(jq -r ".tenants[] | select(.name == \"$tenant_name\")" "$tenant_db")
|
|
|
|
local layers_used layers_max storage_used storage_max
|
|
layers_used=$(echo "$tenant_info" | jq -r '.quotas.used_layers')
|
|
layers_max=$(echo "$tenant_info" | jq -r '.quotas.max_layers')
|
|
storage_used=$(echo "$tenant_info" | jq -r '.quotas.used_storage_gb')
|
|
storage_max=$(echo "$tenant_info" | jq -r '.quotas.max_storage_gb')
|
|
|
|
echo "📊 Resource Usage:"
|
|
echo " Layers: $layers_used/$layers_max"
|
|
echo " Storage: ${storage_used}GB/${storage_max}GB"
|
|
|
|
# Check for quota warnings
|
|
local layer_percent=$((layers_used * 100 / layers_max))
|
|
local storage_percent=$((storage_used * 100 / storage_max))
|
|
|
|
if [[ $layer_percent -gt 80 ]]; then
|
|
echo "⚠️ Layer quota usage high: ${layer_percent}%"
|
|
fi
|
|
|
|
if [[ $storage_percent -gt 80 ]]; then
|
|
echo "⚠️ Storage quota usage high: ${storage_percent}%"
|
|
fi
|
|
|
|
echo "✅ Tenant health check complete"
|
|
}
|
|
|
|
# Multi-tenant command handler
|
|
handle_multi_tenant_command() {
|
|
local command="$1"
|
|
shift
|
|
|
|
case "$command" in
|
|
"init")
|
|
init_multi_tenant_system
|
|
;;
|
|
"create")
|
|
local tenant_name="$1"
|
|
local config_file="$2"
|
|
create_tenant "$tenant_name" "$config_file"
|
|
;;
|
|
"delete")
|
|
local tenant_name="$1"
|
|
local force="$2"
|
|
delete_tenant "$tenant_name" "$force"
|
|
;;
|
|
"list")
|
|
local format="$1"
|
|
list_tenants "$format"
|
|
;;
|
|
"info")
|
|
local tenant_name="$1"
|
|
local format="$2"
|
|
get_tenant_info "$tenant_name" "$format"
|
|
;;
|
|
"quota")
|
|
local tenant_name="$1"
|
|
local quota_type="$2"
|
|
local value="$3"
|
|
update_tenant_quotas "$tenant_name" "$quota_type" "$value"
|
|
;;
|
|
"backup")
|
|
local tenant_name="$1"
|
|
local backup_path="$2"
|
|
backup_tenant "$tenant_name" "$backup_path"
|
|
;;
|
|
"restore")
|
|
local backup_file="$1"
|
|
local tenant_name="$2"
|
|
restore_tenant "$backup_file" "$tenant_name"
|
|
;;
|
|
"health")
|
|
local tenant_name="$1"
|
|
check_tenant_health "$tenant_name"
|
|
;;
|
|
"help"|*)
|
|
echo "Multi-Tenant Commands:"
|
|
echo "====================="
|
|
echo " init - Initialize multi-tenant system"
|
|
echo " create <tenant> [config_file] - Create new tenant"
|
|
echo " delete <tenant> [--force] - Delete tenant"
|
|
echo " list [format] - List tenants (json|csv|table)"
|
|
echo " info <tenant> [format] - Get tenant info (json|yaml|summary)"
|
|
echo " quota <tenant> <type> <value> - Update tenant quota"
|
|
echo " backup <tenant> [path] - Backup tenant"
|
|
echo " restore <backup_file> <tenant> - Restore tenant"
|
|
echo " health <tenant> - Check tenant health"
|
|
echo " help - Show this help"
|
|
;;
|
|
esac
|
|
}
|