409 lines
13 KiB
Plaintext
Raw Permalink Normal View History

# Configuration Migration Module
# Handles migration from existing workspace configurations to new setup system
# Follows Nushell guidelines: explicit types, single purpose, no try-catch
use ./mod.nu *
use ./detection.nu *
# ============================================================================
# EXISTING CONFIGURATION DETECTION
# ============================================================================
# Detect existing workspace configuration
export def detect-existing-workspace [
workspace_path: string
]: nothing -> record {
let config_path = $"($workspace_path)/config/provisioning.yaml"
let providers_path = $"($workspace_path)/.providers"
let infra_path = $"($workspace_path)/infra"
{
workspace_path: $workspace_path
has_config: ($config_path | path exists)
config_path: $config_path
has_providers: ($providers_path | path exists)
providers_path: $providers_path
has_infra: ($infra_path | path exists)
infra_path: $infra_path
}
}
# Find existing workspace directories
export def find-existing-workspaces []: nothing -> list<string> {
mut workspaces = []
# Check common workspace locations
let possible_paths = [
"workspace_librecloud"
"./workspace_librecloud"
"../workspace_librecloud"
"workspaces"
"./workspaces"
]
for path in $possible_paths {
let expanded_path = ($path | path expand)
if ($expanded_path | path exists) and (($expanded_path | path type) == "dir") {
let workspace_config = $"($expanded_path)/config/provisioning.yaml"
if ($workspace_config | path exists) {
$workspaces = ($workspaces | append $expanded_path)
}
}
}
$workspaces
}
# ============================================================================
# CONFIGURATION MIGRATION
# ============================================================================
# Migrate workspace configuration from YAML to new system
export def migrate-workspace-config [
workspace_path: string
config_base: string
--backup = true
]: nothing -> record {
let source_config = $"($workspace_path)/config/provisioning.yaml"
if not ($source_config | path exists) {
return {
success: false
error: "Source configuration not found"
}
}
# Load existing configuration
let existing_config = (load-config-yaml $source_config)
# Extract workspace name from path
let workspace_name = ($workspace_path | path basename)
# Create backup if requested
if $backup {
let timestamp_for_backup = (get-timestamp-iso8601 | str replace -a ':' '-')
let backup_path = $"($config_base)/migration-backup-($workspace_name)-($timestamp_for_backup).yaml"
let backup_result = (do { cp $source_config $backup_path } | complete)
if ($backup_result.exit_code != 0) {
print-setup-warning $"Failed to create backup at ($backup_path)"
} else {
print-setup-success $"Configuration backed up to ($backup_path)"
}
}
# Create migration record
{
success: true
workspace_name: $workspace_name
source_path: $source_config
migrated_at: (get-timestamp-iso8601)
backup_created: $backup
}
}
# Migrate provider configurations
export def migrate-provider-configs [
workspace_path: string
config_base: string
]: nothing -> record {
let providers_source = $"($workspace_path)/.providers"
if not ($providers_source | path exists) {
return {
success: false
migrated_providers: []
error: "No provider directory found"
}
}
mut migrated = []
# Get list of provider directories
let result = (do {
ls $providers_source | where type == "dir"
} | complete)
if ($result.exit_code != 0) {
return {
success: false
migrated_providers: []
error: "Failed to read provider directories"
}
}
# Migrate each provider
for provider_entry in $result.stdout {
let provider_name = ($provider_entry | str trim)
if ($provider_name | str length) > 0 {
print-setup-info $"Migrating provider: ($provider_name)"
$migrated = ($migrated | append $provider_name)
}
}
let success_status = ($migrated | length) > 0
let migrated_at_value = (get-timestamp-iso8601)
{
success: $success_status
migrated_providers: $migrated
source_path: $providers_source
migrated_at: $migrated_at_value
}
}
# ============================================================================
# MIGRATION VALIDATION
# ============================================================================
# Validate migration can proceed safely
export def validate-migration [
workspace_path: string
config_base: string
]: nothing -> record {
mut warnings = []
mut errors = []
# Check source workspace exists
if not ($workspace_path | path exists) {
$errors = ($errors | append "Source workspace path does not exist")
}
# Check configuration base exists
if not ($config_base | path exists) {
$errors = ($errors | append "Target configuration base does not exist")
}
# Check if migration already happened
let migration_marker = $"($config_base)/migration_completed.yaml"
if ($migration_marker | path exists) {
$warnings = ($warnings | append "Migration appears to have been run before")
}
# Check for conflicts
let workspace_name = ($workspace_path | path basename)
let registry_path = $"($config_base)/workspaces_registry.yaml"
if ($registry_path | path exists) {
let registry = (load-config-yaml $registry_path)
if ($registry.workspaces? | default [] | any { |w| $w.name == $workspace_name }) {
$warnings = ($warnings | append $"Workspace '($workspace_name)' already registered")
}
}
let can_proceed_status = ($errors | length) == 0
let error_count_value = ($errors | length)
let warning_count_value = ($warnings | length)
{
can_proceed: $can_proceed_status
errors: $errors
warnings: $warnings
error_count: $error_count_value
warning_count: $warning_count_value
}
}
# ============================================================================
# MIGRATION EXECUTION
# ============================================================================
# Execute complete workspace migration
export def execute-migration [
workspace_path: string
config_base: string = ""
--backup = true
--verbose = false
]: nothing -> record {
let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })
print-setup-header "Workspace Configuration Migration"
print ""
# Validate migration can proceed
let validation = (validate-migration $workspace_path $base)
if not $validation.can_proceed {
for error in $validation.errors {
print-setup-error $error
}
return {
success: false
errors: $validation.errors
}
}
# Show warnings
if ($validation.warnings | length) > 0 {
for warning in $validation.warnings {
print-setup-warning $warning
}
}
print ""
print-setup-info "Starting migration process..."
print ""
# Step 1: Migrate workspace configuration
print-setup-info "Migrating workspace configuration..."
let config_migration = (migrate-workspace-config $workspace_path $base --backup=$backup)
if not $config_migration.success {
print-setup-error $config_migration.error
return {
success: false
error: $config_migration.error
}
}
print-setup-success "Workspace configuration migrated"
# Step 2: Migrate provider configurations
print-setup-info "Migrating provider configurations..."
let provider_migration = (migrate-provider-configs $workspace_path $base)
if $provider_migration.success {
print-setup-success $"Migrated ($provider_migration.migrated_providers | length) providers"
} else {
print-setup-warning "No provider configurations to migrate"
}
# Step 3: Create migration marker
let workspace_name = ($workspace_path | path basename)
let migration_marker_path = $"($base)/migration_completed.yaml"
let migration_record = {
version: "1.0.0"
completed_at: (get-timestamp-iso8601)
workspace_migrated: $workspace_name
source_path: $workspace_path
target_path: $base
backup_created: $backup
}
let save_result = (save-config-yaml $migration_marker_path $migration_record)
if not $save_result {
print-setup-warning "Failed to create migration marker"
}
print ""
print-setup-success "Migration completed successfully!"
print ""
# Summary
print "Migration Summary:"
print $" Source Workspace: ($workspace_path)"
print $" Target Config Base: ($base)"
print $" Configuration Migrated: ✅"
print $" Providers Migrated: ($provider_migration.migrated_providers | length)"
if $backup {
print " Backup Created: ✅"
}
print ""
{
success: true
workspace_name: $workspace_name
config_migration: $config_migration
provider_migration: $provider_migration
migration_completed_at: (get-timestamp-iso8601)
}
}
# ============================================================================
# MIGRATION ROLLBACK
# ============================================================================
# Rollback migration from backup
export def rollback-migration [
workspace_name: string
config_base: string = ""
--restore_backup = true
]: nothing -> record {
let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })
print-setup-header "Rolling Back Migration"
print ""
print-setup-warning "Initiating migration rollback..."
print ""
# Find and restore backup
let migration_marker = $"($base)/migration_completed.yaml"
if not ($migration_marker | path exists) {
print-setup-error "No migration record found - cannot rollback"
return {
success: false
error: "No migration record found"
}
}
let migration_record = (load-config-yaml $migration_marker)
# Find backup file
let backup_pattern = $"($base)/migration-backup-($workspace_name)-*.yaml"
print-setup-info $"Looking for backup matching: ($backup_pattern)"
# Remove migration artifacts
if ($migration_marker | path exists) {
let rm_result = (do { rm $migration_marker } | complete)
if ($rm_result.exit_code == 0) {
print-setup-success "Migration marker removed"
}
}
print ""
print-setup-success "Migration rollback completed"
print ""
print "Note: Please verify your workspace is in the desired state"
{
success: true
workspace_name: $workspace_name
rolled_back_at: (get-timestamp-iso8601)
}
}
# ============================================================================
# AUTO-MIGRATION
# ============================================================================
# Automatically detect and migrate existing workspaces
export def auto-migrate-existing [
config_base: string = ""
--verbose = false
]: nothing -> record {
let base = (if ($config_base == "") { (get-config-base-path) } else { $config_base })
print-setup-header "Detecting Existing Workspaces"
print ""
# Find existing workspaces
let existing = (find-existing-workspaces)
if ($existing | length) == 0 {
print-setup-info "No existing workspaces detected"
return {
success: true
workspaces_found: 0
workspaces: []
}
}
print-setup-success $"Found ($existing | length) existing workspace(s)"
print ""
mut migrated = []
for workspace_path in $existing {
let workspace_name = ($workspace_path | path basename)
print-setup-info $"Auto-migrating: ($workspace_name)"
let migration_result = (execute-migration $workspace_path $base --verbose=$verbose)
if $migration_result.success {
$migrated = ($migrated | append $workspace_name)
}
}
{
success: true
workspaces_found: ($existing | length)
workspaces: $existing
migrated_count: ($migrated | length)
migrated_workspaces: $migrated
timestamp: (get-timestamp-iso8601)
}
}