DataContainer-Utils.psm1
$ErrorActionPreference = 'stop' Import-Module "$PSScriptRoot/Utils.psm1" function Get-ParentPath { param( # Path [Parameter(Mandatory = $true)] [string] $Path ) return ($Path -split '/' | Select-Object -SkipLast 1) -join "/" } function Backup-DataContainer ($Config) { $ErrorActionPreference = 'stop' $backupImage = "$($Config.remoteName)-data" # $volumeArgs = ($Config.volumes | ForEach-Object { "'-v' '$_'" }) -join " " $cpCmds = ($Config.volumes | ForEach-Object { $parent = Get-ParentPath "/backup$_" "mkdir -p /backup$_ && cp -vRf $_ $parent" }) -join " && " Write-Output "Backup local container $($Config.container)'s volumes to ops-backup-$backupImage" Write-Output "Invoking: 'docker' 'run' '--volumes-from' '$($Config.container):ro' '--name' 'ops-backup-$backupImage' 'alpine' 'sh' -c '$cpCmds'" # backup data container's volumes Invoke-Cmd "'docker' 'run' '--volumes-from' '$($Config.container):ro' '--name' 'ops-backup-$backupImage' 'alpine' 'sh' -c '$cpCmds'" # commit backup to registry $remote = "$($Config.registry)$backupImage" $date = Get-Date -Format "yyyy-MM-dd-HH-mm-ss" Invoke-Cmd "'docker' 'commit' 'ops-backup-$backupImage' '$($remote):$date'" Invoke-Cmd "docker tag '$($remote):$date' '$($remote):latest'" Write-Output "Pushing: '$($remote):$date'" Invoke-Cmd "'docker' 'push' '$($remote):$date'" Invoke-Cmd "'docker' 'push' '$($remote):latest'" Invoke-Cmd "docker rm -f 'ops-backup-$backupImage'" } function Restore-DataContainer ($Config) { $backupImage = "$($Config.remoteName)-data" $remote = "$($Config.registry)$backupImage" $volumeArgs = ($Config.volumes | ForEach-Object { "'-v' '$_'" }) -join " " $cpCmds = ($Config.volumes | ForEach-Object { $parent = Get-ParentPath "$_" "mkdir -p $_ && cp -vRf /backup$_ $parent" }) -join " && " Write-Output "Restore $remote to local container $backupImage" # pull latest images Invoke-Cmd "docker pull '$remote'" Write-Output "Invoking: 'docker' 'run' $volumeArgs '--name' '$backupImage' '$remote' 'sh' -c '$cpCmds'" Invoke-Cmd "'docker' 'run' $volumeArgs '--name' '$backupImage' '$remote' 'sh' -c '$cpCmds && rm -rf /backup'" } function Backup-FromConfig { param( # ConfigFile [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_} )] [string] $ConfigFile ) $ErrorActionPreference = 'stop' $configs = Get-Content $ConfigFile -Raw | ConvertFrom-Json foreach ($cfg in $configs) { Backup-DataContainer($cfg) } } function Restore-FromConfig { param( # ConfigFile [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_} )] [string] $ConfigFile ) $ErrorActionPreference = 'stop' $configs = Get-Content $ConfigFile -Raw | ConvertFrom-Json foreach ($cfg in $configs) { Restore-DataContainer($cfg) } } function Get-DataContainerConfig { param( # ConfigFile [Parameter(Mandatory = $true)] [ValidateScript( {Test-Path $_} )] [string] $ConfigFile ) $ErrorActionPreference = 'stop' $configs = Get-Content $ConfigFile -Raw | ConvertFrom-Json foreach ($cfg in $configs) { Write-Output "$($cfg.container) >> $($cfg.registry)$($cfg.remoteName)-data" foreach ($path in $cfg.volumes) { Write-Output " $path" } Write-Output "" } } function Convert-VolumesJson { param( # JsonOutput [Parameter(Mandatory = $true)] [string] $JsonOutput ) [string[]]$result = $JsonOutput | ConvertFrom-Json | Get-Member ` | Where-Object { $_.MemberType -eq "NoteProperty"} ` | ForEach-Object { $_.Name} if ($result -isnot [array]) { $result = @($result) } return $result } function New-BackupConfig { param( # ConfigFile [Parameter(Mandatory = $true)] [string] $ConfigFile, # Registry [Parameter(Mandatory = $true)] [string] $Registry ) if (-not $Registry.EndsWith('/')) { $Registry += '/' } [array]$config = Invoke-Cmd "'docker' 'ps' '-a' '--format={{json .Names}}'" ` | ForEach-Object { $_.Trim("`"") } ` | ForEach-Object { $volumesJson = Invoke-Cmd "'docker' 'inspect' '$_' '--format={{json .Config.Volumes}}'" if ($volumesJson -eq 'null') { return $null } [string[]]$volumes = Convert-VolumesJson $volumesJson $res = @{ registry = $Registry; container = $_; volumes = $volumes; remoteName = $_.ToLower(); } return $res } ` | Where-Object {$_ -ne $null} ConvertTo-Json -InputObject $config | Out-File -FilePath $ConfigFile -Encoding utf8 -Force } |