fast-build-update-tool/internal/tools/update_script_generator_windows_fleet.go (167 lines of code) (raw):
package tools
import (
"io"
"path/filepath"
"strings"
"text/template"
"github.com/aws/amazon-gamelift-toolkit/fast-build-update-tool/internal/config"
)
// generateLinuxUpdateScript is used to generate an update script for a Windows fleet
// updateOperation configures which type of update script will be generated
func generateWindowsUpdateScript(writer io.Writer, executablePaths []string, localBuildZipPath, lockName string, updateOperation config.UpdateOperation) error {
template, err := template.New("windows-update-template").Parse(windowsUpdateScriptTemplate)
if err != nil {
return err
}
processNames := make([]string, len(executablePaths))
for i, executablePath := range executablePaths {
parts := strings.Split(executablePath, "\\")
exeName := parts[len(parts)-1]
processNames[i] = strings.Replace(exeName, ".exe", "", -1)
}
return template.Execute(writer, map[string]string{
"ArchiveName": filepath.Base(localBuildZipPath),
"ExecutablePaths": csvify(executablePaths),
"ProcessNames": csvify(processNames),
"IsReplaceBuild": getIsReplaceBuildTemplateValue(updateOperation),
"LockName": lockName,
})
}
const windowsUpdateScriptTemplate = `
$ErrorActionPreference = "Stop";
[bool]$wasLockCreated = $false;
[System.Threading.Mutex]$mutex;
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.ZipFile")
$baseDir="C:\Game\";
$unzipDir="C:\GameNew\";
$executablePaths="{{ .ExecutablePaths }}" -split ",";
$processNames="{{ .ProcessNames }}" -split ",";
$zipFileName="{{ .ArchiveName }}";
$archivePath="C:\Users\gl-user-server\$zipFileName";
try {
$mutex = New-Object System.Threading.Mutex($true, "Global\{{ .LockName }}", [ref]$wasLockCreated);
if (!$wasLockCreated)
{
Write-Host "ERROR! Couldn't acquire update lock, exiting...";
exit 1;
}
Write-Host "Acquired update lock";
function KillAll-ServerProcess {
param (
[string]$ProcessToKill
)
Write-Host "Stopping all processes with name: $ProcessToKill";
$serverProcesses = Get-Process -Name $ProcessToKill -ErrorAction SilentlyContinue;
if ($serverProcesses) {
Write-Host "Stopping the old server processes";
foreach ($process in $serverProcesses) {
Write-Host "Stopping the process with id: " $process.Id;
# Stop the process
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue;
# Wait for the process to exit
Wait-Process -Id $process.Id -ErrorAction SilentlyContinue;
Write-Host "Done stopping the process with id: " $process.Id;
}
} else {
Write-Host "No running process found: $ProcessToKill";
}
}
Write-Host "===========================================================";
Write-Host "Ending running server processes";
Write-Host "===========================================================";
{{if .IsReplaceBuild}}
foreach ($executablePath in $executablePaths) {
if (Test-Path $executablePath) {
Write-Host "Moving old executable to $executablePath-old";
Move-Item -Force -Path $executablePath -Destination $executablePath-old;
} else {
Write-Host "Executable $executablePath not found";
}
}
{{end}}
foreach ($processName in $processNames) {
KillAll-ServerProcess $processName;
}
{{if .IsReplaceBuild}}
Start-Sleep -Seconds 5;
Write-Host "===========================================================";
Write-Host "Removing files found in the build zip from the server";
Write-Host "===========================================================";
$zip=[System.IO.Compression.ZipFile]::OpenRead($archivePath);
try {
$zip.Entries | ForEach-Object {
$isDirectory= $_.FullName[-1] -eq '/' -or $_.FullName[-1] -eq '\';
if (!$isDirectory) {
$fileName= $_.FullName -replace '/', '\';
$removePath=$baseDir + $fileName;
if (Test-Path $removePath)
{
Write-Host "Removing old build file: $removePath";
Remove-Item -Path $removePath -Force;
} else {
Write-Host "File from build zip file: $removePath, not seen on the server.";
}
}
}
} catch {
Write-Host "An unexpected error occurred:"
Write-Host $_
throw $_
} finally {
$zip.Dispose();
}
Write-Host "===========================================================";
Write-Host "Expanding $archivePath to $unzipDir";
Write-Host "===========================================================";
Expand-Archive -Path $archivePath -DestinationPath $unzipDir -Force;
Write-Host "===========================================================";
Write-Host "Moving files from $unzipDir to $baseDir";
Write-Host "===========================================================";
Get-ChildItem -Path $unzipDir -Recurse | ForEach-Object {
$name=$_.FullName;
$destination = Join-Path -Path $baseDir -ChildPath $name.Substring($unzipDir.Length);
if ($executablePaths -contains $destination) {
Write-Host "Found executable $destination, this must be copied last";
} else {
$destinationDir = Split-Path -Path $destination -Parent;
if (Test-Path -Path $destinationDir) {
} else {
Write-Host "Missing host dir creating it: $destinationDir";
New-Item -Path $destinationDir -ItemType Directory | Out-Null;
}
if (Test-Path $destination) {
} else {
Write-Host "Moving file to $destination";
Move-Item -Path $_.FullName -Destination $destination -Force;
}
}
}
foreach ($executablePath in $executablePaths) {
$unzipPath = Join-Path -Path $unzipDir -ChildPath $executablePath.Substring($baseDir.Length);
Write-Host "Moving executable file $unzipPath to $executablePath";
Move-Item -Path $unzipPath -Destination $executablePath -Force;
if (Test-Path $executablePath-old) {
Write-Host "Removing $executablePath-old";
Remove-Item -Path $executablePath-old;
}
}
{{end}}
} catch {
Write-Host "An unexpected error occurred:"
Write-Host $_
throw $_
} finally {
if ($wasLockCreated -and $null -ne $mutex) {
$mutex.ReleaseMutex()
$mutex.Dispose()
Write-Host "Update lock released"
}
{{if .IsReplaceBuild}}
Write-Host "Cleaning up archive $archivePath";
Remove-Item -Path $archivePath -Force;
if (Test-Path $unzipDir) {
Remove-Item -Recurse -Force -Path $unzipDir;
}
{{end}}
Write-Host "Cleaning up update script $PSCommandPath";
Remove-Item $PSCommandPath -Force;
}
`