302 lines
7.0 KiB
Markdown
302 lines
7.0 KiB
Markdown
|
|
# Script Refactoring Guide
|
||
|
|
|
||
|
|
This guide explains how to refactor existing scripts to use the new common library structure.
|
||
|
|
|
||
|
|
## Quick Start
|
||
|
|
|
||
|
|
### Before (Old Pattern)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
|
|
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
NC='\033[0m'
|
||
|
|
|
||
|
|
# Load subscription ID
|
||
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||
|
|
export $(grep -v '^#' "$PROJECT_ROOT/.env" | grep AZURE_SUBSCRIPTION_ID | xargs)
|
||
|
|
fi
|
||
|
|
|
||
|
|
SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:-fc08d829-4f14-413d-ab27-ce024425db0b}"
|
||
|
|
|
||
|
|
# Check Azure CLI
|
||
|
|
if ! command -v az &> /dev/null; then
|
||
|
|
echo -e "${RED}Error: Azure CLI not found${NC}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check Azure login
|
||
|
|
az account show &> /dev/null || {
|
||
|
|
echo -e "${RED}Error: Not logged in to Azure${NC}"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
az account set --subscription "$SUBSCRIPTION_ID" &> /dev/null || true
|
||
|
|
|
||
|
|
echo -e "${GREEN}Starting script...${NC}"
|
||
|
|
```
|
||
|
|
|
||
|
|
### After (New Pattern)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
||
|
|
|
||
|
|
# Initialize Azure
|
||
|
|
SUBSCRIPTION_ID="$(get_subscription_id)"
|
||
|
|
ensure_azure_cli || exit 1
|
||
|
|
set_subscription "$SUBSCRIPTION_ID" || true
|
||
|
|
|
||
|
|
log_info "Starting script..."
|
||
|
|
```
|
||
|
|
|
||
|
|
## Migration Checklist
|
||
|
|
|
||
|
|
### Step 1: Add Library Sourcing
|
||
|
|
|
||
|
|
Replace:
|
||
|
|
```bash
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
|
|
```
|
||
|
|
|
||
|
|
With:
|
||
|
|
```bash
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note**: `PROJECT_ROOT` is automatically set by the library.
|
||
|
|
|
||
|
|
### Step 2: Remove Color Definitions
|
||
|
|
|
||
|
|
Remove:
|
||
|
|
```bash
|
||
|
|
RED='\033[0;31m'
|
||
|
|
GREEN='\033[0;32m'
|
||
|
|
YELLOW='\033[1;33m'
|
||
|
|
NC='\033[0m'
|
||
|
|
```
|
||
|
|
|
||
|
|
Use logging functions instead:
|
||
|
|
```bash
|
||
|
|
log_info "Message"
|
||
|
|
log_warn "Warning"
|
||
|
|
log_error "Error"
|
||
|
|
log_success "Success"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 3: Replace Echo Statements
|
||
|
|
|
||
|
|
| Old | New |
|
||
|
|
|-----|-----|
|
||
|
|
| `echo -e "${GREEN}Success${NC}"` | `log_success "Success"` |
|
||
|
|
| `echo -e "${RED}Error${NC}"` | `log_error "Error"` |
|
||
|
|
| `echo -e "${YELLOW}Warning${NC}"` | `log_warn "Warning"` |
|
||
|
|
| `echo "Info"` | `log_info "Info"` |
|
||
|
|
|
||
|
|
### Step 4: Replace Azure CLI Checks
|
||
|
|
|
||
|
|
Remove:
|
||
|
|
```bash
|
||
|
|
if ! command -v az &> /dev/null; then
|
||
|
|
echo -e "${RED}Error: Azure CLI not found${NC}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
az account show &> /dev/null || {
|
||
|
|
echo -e "${RED}Error: Not logged in${NC}"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Replace with:
|
||
|
|
```bash
|
||
|
|
ensure_azure_cli || exit 1
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 5: Replace Subscription Loading
|
||
|
|
|
||
|
|
Remove:
|
||
|
|
```bash
|
||
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||
|
|
export $(grep -v '^#' "$PROJECT_ROOT/.env" | grep AZURE_SUBSCRIPTION_ID | xargs)
|
||
|
|
fi
|
||
|
|
|
||
|
|
SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:-fc08d829-4f14-413d-ab27-ce024425db0b}"
|
||
|
|
az account set --subscription "$SUBSCRIPTION_ID" &> /dev/null || true
|
||
|
|
```
|
||
|
|
|
||
|
|
Replace with:
|
||
|
|
```bash
|
||
|
|
SUBSCRIPTION_ID="$(get_subscription_id)"
|
||
|
|
set_subscription "$SUBSCRIPTION_ID" || true
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 6: Replace Region Code Mappings
|
||
|
|
|
||
|
|
Remove large `declare -A REGION_CODES` blocks and replace with:
|
||
|
|
```bash
|
||
|
|
# Get all regions
|
||
|
|
get_all_regions
|
||
|
|
|
||
|
|
# Get specific region code
|
||
|
|
CODE=$(get_region_code "westeurope") # Returns "wst"
|
||
|
|
|
||
|
|
# Get region name from code
|
||
|
|
REGION=$(get_region_name "wst") # Returns "westeurope"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Common Patterns
|
||
|
|
|
||
|
|
### Pattern 1: Script with Azure Operations
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
||
|
|
|
||
|
|
ensure_azure_cli || exit 1
|
||
|
|
|
||
|
|
log_section "Script Title"
|
||
|
|
|
||
|
|
# Your script logic here
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pattern 2: Script with Region Iteration
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
||
|
|
|
||
|
|
ensure_azure_cli || exit 1
|
||
|
|
|
||
|
|
log_section "Processing Regions"
|
||
|
|
|
||
|
|
while IFS=':' read -r region_name region_code; do
|
||
|
|
log_info "Processing $region_name ($region_code)..."
|
||
|
|
# Your logic here
|
||
|
|
done < <(get_all_regions)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pattern 3: Script with Error Handling
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
set -e
|
||
|
|
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
source "$SCRIPT_DIR/../lib/init.sh"
|
||
|
|
|
||
|
|
ensure_azure_cli || exit 1
|
||
|
|
|
||
|
|
ERRORS=()
|
||
|
|
|
||
|
|
# Process items
|
||
|
|
for item in "${ITEMS[@]}"; do
|
||
|
|
if ! process_item "$item"; then
|
||
|
|
ERRORS+=("$item")
|
||
|
|
log_error "Failed to process $item"
|
||
|
|
else
|
||
|
|
log_success "Processed $item"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# Report errors
|
||
|
|
if [ ${#ERRORS[@]} -gt 0 ]; then
|
||
|
|
log_warn "Failed to process ${#ERRORS[@]} items"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
log_success "All items processed successfully"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Available Library Functions
|
||
|
|
|
||
|
|
### Logging (`lib/common/logging.sh`)
|
||
|
|
- `log_debug "message"` - Debug level log
|
||
|
|
- `log_info "message"` - Info level log
|
||
|
|
- `log_warn "message"` - Warning log
|
||
|
|
- `log_error "message"` - Error log
|
||
|
|
- `log_success "message"` - Success message
|
||
|
|
- `log_failure "message"` - Failure message
|
||
|
|
- `log_section "title"` - Section header
|
||
|
|
- `log_subsection "title"` - Subsection header
|
||
|
|
|
||
|
|
### Colors (`lib/common/colors.sh`)
|
||
|
|
- `color_red "text"` - Red text
|
||
|
|
- `color_green "text"` - Green text
|
||
|
|
- `color_yellow "text"` - Yellow text
|
||
|
|
- `color_blue "text"` - Blue text
|
||
|
|
- `color_cyan "text"` - Cyan text
|
||
|
|
|
||
|
|
### Azure CLI (`lib/azure/cli.sh`)
|
||
|
|
- `check_azure_cli` - Check if Azure CLI is installed
|
||
|
|
- `check_azure_login` - Check if logged in
|
||
|
|
- `ensure_azure_cli` - Ensure CLI is ready (installed + logged in)
|
||
|
|
- `get_current_subscription` - Get current subscription ID
|
||
|
|
- `get_current_subscription_name` - Get current subscription name
|
||
|
|
|
||
|
|
### Configuration (`lib/config/`)
|
||
|
|
- `get_subscription_id` - Get subscription ID from env or default
|
||
|
|
- `set_subscription "id"` - Set Azure subscription
|
||
|
|
- `get_region_code "name"` - Get 3-char region code
|
||
|
|
- `get_region_name "code"` - Get region name from code
|
||
|
|
- `get_all_regions` - Get all regions (name:code format)
|
||
|
|
- `is_valid_region_code "code"` - Validate region code
|
||
|
|
|
||
|
|
### Utilities (`lib/common/utils.sh`)
|
||
|
|
- `require_command "cmd" ["hint"]` - Require command exists
|
||
|
|
- `command_exists "cmd"` - Check if command exists
|
||
|
|
- `confirm "prompt" ["default"]` - Confirm action
|
||
|
|
- `is_dry_run` - Check if in dry-run mode
|
||
|
|
- `print_header "title" ["width"]` - Print header box
|
||
|
|
|
||
|
|
## Testing Refactored Scripts
|
||
|
|
|
||
|
|
1. Test with `--dry-run` if supported
|
||
|
|
2. Verify output formatting matches original
|
||
|
|
3. Check error messages are clear
|
||
|
|
4. Ensure backward compatibility if script is called by others
|
||
|
|
|
||
|
|
## Examples
|
||
|
|
|
||
|
|
See `scripts/azure/check-naming-conventions.sh.refactored` for a complete example of a refactored script.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Example migrated scripts (as references):
|
||
|
|
# - scripts/deployment/fix-resource-groups-and-keyvaults.sh
|
||
|
|
# - scripts/azure/list-all-resources.sh
|
||
|
|
# - scripts/key-management/manage-keyvaults.sh
|
||
|
|
# - scripts/key-management/azure-keyvault-setup.sh
|
||
|
|
# - scripts/key-management/store-nodes-in-keyvault.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Syntax check only (no execution):
|
||
|
|
bash -n scripts/azure/list-all-resources.sh
|
||
|
|
bash -n scripts/key-management/manage-keyvaults.sh
|
||
|
|
bash -n scripts/key-management/azure-keyvault-setup.sh
|
||
|
|
bash -n scripts/key-management/store-nodes-in-keyvault.sh
|
||
|
|
|
||
|
|
# Dry run (where supported):
|
||
|
|
DRY_RUN=1 scripts/key-management/store-nodes-in-keyvault.sh
|
||
|
|
```
|
||
|
|
|