File size: 6,740 Bytes
b7931c0
 
 
f2f92fc
 
 
 
b7931c0
 
 
 
 
 
f2f92fc
 
 
 
b7931c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357bf18
 
 
 
 
 
 
 
 
 
 
 
b7931c0
f2f92fc
 
 
 
 
 
 
 
 
 
 
 
 
b7931c0
 
 
 
 
 
 
 
 
f2f92fc
b7931c0
 
 
 
 
 
 
 
f2f92fc
 
b7931c0
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Simple script to update files on all instances using EC2 Instance Connect
# 
# Usage Examples:
#   .\update-pm-files.ps1                                           # Updates exposure_spread.py (default)
#   .\update-pm-files.ps1 -FileName "predict_dupes.py"              # Updates predict_dupes.py
#   .\update-pm-files.ps1 -FileName "app.py"                        # Updates app.py and auto-restarts Streamlit
#   .\update-pm-files.ps1 -FileName "predict_dupes.py" -RestartStreamlit  # Updates predict_dupes.py and forces Streamlit restart
#
param(
    [Parameter(Mandatory=$false)]
    [string]$FileName = "exposure_spread.py",
    
    [Parameter(Mandatory=$false)]
    [string]$TargetPath = "/home/ec2-user/AWS_Portfolio_Manager/global_func/",
    
    [Parameter(Mandatory=$false)]
    [switch]$RestartStreamlit
)

# Handle special case: app.py maps to application.py on the remote instances
$remoteFileName = $FileName
if ($FileName -eq "app.py") {
    $remoteFileName = "application.py"
    Write-Host "Note: app.py will be uploaded as application.py on remote instances" -ForegroundColor Yellow
}

# Determine local file path - check global_func first, then root directory
$localFilePath = ""
if (Test-Path ".\global_func\$FileName") {
    $localFilePath = ".\global_func\$FileName"
} elseif (Test-Path ".\$FileName") {
    $localFilePath = ".\$FileName"
    # If uploading from root and no target path specified, default to root on remote
    if ($TargetPath -eq "/home/ec2-user/AWS_Portfolio_Manager/global_func/") {
        $TargetPath = "/home/ec2-user/AWS_Portfolio_Manager/"
    }
} else {
    Write-Host "Error: File '$FileName' not found!" -ForegroundColor Red
    Write-Host "Checked locations:" -ForegroundColor Yellow
    Write-Host "  .\global_func\$FileName" -ForegroundColor Cyan
    Write-Host "  .\$FileName" -ForegroundColor Cyan
    Write-Host "`nAvailable files in global_func:" -ForegroundColor Yellow
    Get-ChildItem ".\global_func\*.py" -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "  $($_.Name)" -ForegroundColor Cyan }
    Write-Host "`nAvailable files in root:" -ForegroundColor Yellow
    Get-ChildItem ".\*.py" -ErrorAction SilentlyContinue | ForEach-Object { Write-Host "  $($_.Name)" -ForegroundColor Cyan }
    exit 1
}

Write-Host "Updating file: $FileName -> $remoteFileName" -ForegroundColor Green
Write-Host "Local path: $localFilePath" -ForegroundColor Cyan
Write-Host "Target path: $TargetPath$remoteFileName" -ForegroundColor Cyan

# Get instance IPs and IDs
. .\get-ips.ps1
$instanceIds = aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names portfolio-manager-asg --query 'AutoScalingGroups[0].Instances[?HealthStatus==`Healthy`].InstanceId' --output text

if ($global:instances.Count -eq 0) {
    Write-Host "No instances found" -ForegroundColor Red
    exit 1
}

Write-Host "Found $($global:instances.Count) instances: $($global:instances -join ', ')" -ForegroundColor Green

# Generate a temporary SSH key for this session
Write-Host "Generating temporary SSH key..." -ForegroundColor Cyan
ssh-keygen -t rsa -f temp_update_key -N '""' -q

$instanceIdArray = $instanceIds -split "`t"

# Update each instance one at a time to maintain uptime
for ($i = 0; $i -lt $global:instances.Count; $i++) {
    $ip = $global:instances[$i]
    $instanceId = $instanceIdArray[$i]
    
    Write-Host "Updating instance $instanceId ($ip)..." -ForegroundColor Yellow
    
    # Send SSH public key via EC2 Instance Connect
    Write-Host "Sending SSH key to $instanceId..."
    aws ec2-instance-connect send-ssh-public-key --instance-id $instanceId --instance-os-user ec2-user --ssh-public-key file://temp_update_key.pub
    
    if ($LASTEXITCODE -eq 0) {
        # Copy the file using SCP
        Write-Host "Copying $FileName -> $remoteFileName to $ip..."
        scp -i temp_update_key -o StrictHostKeyChecking=no "$localFilePath" ec2-user@${ip}:$TargetPath$remoteFileName
        
        if ($LASTEXITCODE -eq 0) {
            Write-Host "$remoteFileName copied successfully to $ip" -ForegroundColor Green

            # Determine if we should run pip install (for requirements.txt)
            if ($FileName -eq "requirements.txt") {
                Write-Host "requirements.txt detected - Installing dependencies..." -ForegroundColor Magenta
                ssh -i temp_update_key -o StrictHostKeyChecking=no ec2-user@$ip "cd /home/ec2-user/AWS_Portfolio_Manager && ./venv/bin/pip install -r requirements.txt"
                
                if ($LASTEXITCODE -eq 0) {
                    Write-Host "Dependencies installed successfully on $ip" -ForegroundColor Green
                } else {
                    Write-Host "Failed to install dependencies on $ip" -ForegroundColor Red
                }
            }
            
            # Determine if we should restart Streamlit
            $shouldRestart = $false
            if ($FileName -eq "app.py") {
                # Always restart when updating app.py
                $shouldRestart = $true
                Write-Host "app.py detected - Streamlit will be restarted" -ForegroundColor Magenta
            } elseif ($RestartStreamlit) {
                # Restart if explicitly requested via parameter
                $shouldRestart = $true
                Write-Host "RestartStreamlit parameter specified - Streamlit will be restarted" -ForegroundColor Magenta
            }
            
            if ($shouldRestart) {
                Write-Host "Restarting Streamlit service on $ip..."
                ssh -i temp_update_key -o StrictHostKeyChecking=no ec2-user@$ip "pkill -f 'streamlit run' && cd /home/ec2-user/AWS_Portfolio_Manager && nohup ./venv/bin/streamlit run application.py --server.port 5000 --server.address 0.0.0.0 > /dev/null 2>&1 &"
                
                if ($LASTEXITCODE -eq 0) {
                    Write-Host "Service restarted successfully on $ip" -ForegroundColor Green
                } else {
                    Write-Host "Failed to restart service on $ip" -ForegroundColor Red
                }
            } else {
                Write-Host "Skipping Streamlit restart (use -RestartStreamlit to force)" -ForegroundColor Yellow
            }
        } else {
            Write-Host "Failed to copy $remoteFileName to $ip" -ForegroundColor Red
        }
    } else {
        Write-Host "Failed to send SSH key to $instanceId" -ForegroundColor Red
    }
    
    Write-Host "Waiting 3 seconds before next instance..." -ForegroundColor Cyan
    Start-Sleep -Seconds 3
}

# Clean up temporary key files
Remove-Item temp_update_key, temp_update_key.pub -ErrorAction SilentlyContinue

Write-Host "All instances updated with rolling restart!" -ForegroundColor Green